Stored procedure with variable number of parameters
Asked Answered
G

7

24

I have stored procedure where I have to pass parameters, But the problem is I am not sure how many parameters is going to come it can be 1, in next run it can be 5.

cmd.Parameters.Add(new SqlParameter("@id", id)

Can anyone help how can I pass these variable number of parameters in stored procedure? Thanks

Gains answered 18/9, 2011 at 15:45 Comment(4)
To pass a varying number of parameters you would just have conditional logic in your client code to add the required parameters but do you mean that you want to know how to pass a varying number of ids to the stored proc?Featherstitch
yes...its something like passing arrays to stored procedure...but the length of this array can vary.Gains
What RDBMS is this for (including version)?Featherstitch
See sommarskog.se/arrays-in-sql-2008.htmlFeatherstitch
D
31

You could pass it in as a comma-separated list, then use a split function, and join against the results.

CREATE FUNCTION dbo.SplitInts
(
   @List       VARCHAR(MAX),
   @Delimiter  CHAR(1)
)
RETURNS TABLE
AS
   RETURN 
   (
       SELECT Item = CONVERT(INT, Item)
       FROM
       (
           SELECT Item = x.i.value('(./text())[1]', 'INT')
           FROM
           (
               SELECT [XML] = CONVERT(XML, '<i>' 
                    + REPLACE(@List, @Delimiter, '</i><i>') 
                    + '</i>').query('.')
           ) AS a
           CROSS APPLY
           [XML].nodes('i') AS x(i)
       ) AS y
       WHERE Item IS NOT NULL
   );

Now your stored procedure:

CREATE PROCEDURE dbo.doStuff
    @List VARCHAR(MAX)
AS
BEGIN
    SET NOCOUNT ON;

    SELECT cols FROM dbo.table AS t
        INNER JOIN dbo.SplitInts(@List, ',') AS list
        ON t.ID = list.Item;
END
GO

Then to call it:

EXEC dbo.doStuff @List = '1, 2, 3, ...';

You can see some background, other options, and performance comparisons here:

On SQL Server 2016 or above, though, you should look at STRING_SPLIT() and STRING_AGG():

Demirep answered 18/9, 2011 at 20:42 Comment(0)
N
5

SQLServer lets you pass TABLE parameter to the stored procedure. So you can define table type, CREATE TYPE LIST_OF_IDS AS TABLE (id int not null primary key), alter your procedure to accept a variable of this type (it should be readonly).

Nadabb answered 18/9, 2011 at 15:56 Comment(0)
S
5

Stored procedures support optional parameters. Like C# 4, you can specify a default value using =. For example:

create procedure dbo.doStuff(
     @stuffId int = null, 
     @stuffSubId int = null, 
     ...)
as
...

For parameters you don't want to pass, either set them to null or don't add them to cmd.Parameters at all. They will have their default value in the stored procedure

Sarnoff answered 18/9, 2011 at 15:58 Comment(1)
The question was dynamic number of parameters. The method suggested only works for a fixed number of parameters even if the ellipses imply otherwise.Halfmast
L
2

Have you considered using dictionary for that purpose? It will allow you to pass any number of parameters as key-value pairs. Then you'll need just to go through the dictionary and add those parameters to cmd.

void DoStuff(Dictionary<string, object> parameters)
{
    // some code
    foreach(var param in parameters)
    {
        cmd.Parameters.Add(new SqlParameter(param.Key, param.Value);
    }
    // some code
}

In stored procedure itself you'll need to specify default values for the parameters.

CREATE PROCEDURE DoStuff(
     @id INT = NULL,
     @value INT = NULL,
     -- the list of parameters with their default values goes here
     )
AS
-- procedure body
Latinize answered 18/9, 2011 at 15:56 Comment(2)
This is on C# side...How do I read this on sql server side...how will I create procedure?Gains
You could check Andomar's response for procedure sample. Just added similar snippet to have everything in the same place.Latinize
G
0

Here is a code snippet that splits a string based on , as delimiter. You can even parametrize the comma. It's useful on systems that don't have the String_split function yet:

  DECLARE @startindex INT
  DECLARE @commaindex INT
  DECLARE @paramAsString VARCHAR(MAX) -- this represents the input param
  DECLARE @param VARCHAR (1024)
  DECLARE @paramsTable TABLE(param VARCHAR(1024) NOT NULL) -- the splitted params come here

  SET @startindex = 1
  WHILE @startindex < LEN(@paramAsString)
  BEGIN
    SET @commaindex = CHARINDEX(',', @paramAsString, @startindex)

    IF @commaindex = 0
    BEGIN
      SET @param = SUBSTRING(@paramAsString, @startindex, LEN(@paramAsString))
      SET @startindex = LEN(@settlementEntities)
    END
    ELSE
    BEGIN
      SET @param = SUBSTRING(@paramAsString, @startindex, (@commaindex - @startindex))
      SET @startindex = @commaindex + 1
    END
    IF @se IS NOT NULL AND 0 < LEN(RTRIM(LTRIM(@param)))
    BEGIN
      SET @param = RTRIM(LTRIM(@param))
      INSERT INTO @paramsTable (param) VALUES (@param)
    END
  END
Grannias answered 27/3, 2018 at 10:49 Comment(0)
H
0

Another way you could do this is by serializing the arguments as a JSON string and passing that into your stored procedure. You can use the NewtonSoft.JSON package to do something like this: string json = JsonConvert.SerializeObject(obj); and pass the json var into your proc.

Hickie answered 12/8, 2022 at 17:32 Comment(0)
P
-1

if you have Sql Server 2008 or later, you can use a table valued parameter...

https://blog.sqlauthority.com/2008/08/31/sql-server-table-valued-parameters-in-sql-server-2008/

Paralogism answered 6/12, 2018 at 17:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.