存储过程具有可变数量的参数

时间:2011-09-18 15:45:39

标签: sql sql-server-2008 sql-server-2008-r2

我有存储过程,我必须传递参数,但问题是我不确定有多少参数可以是1,在下次运行时它可以是5.

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

任何人都可以帮助我如何在存储过程中传递这些可变数量的参数? 感谢

6 个答案:

答案 0 :(得分:19)

您可以将其作为以逗号分隔的列表传递,然后使用拆分功能,并根据结果加入。

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
   );

现在您的存储过程:

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

然后调用它:

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

您可以在此处查看一些背景,其他选项和效果比较:

在SQL Server 2016或更高版本上,您应该查看STRING_SPLIT()STRING_AGG()

答案 1 :(得分:6)

存储过程支持可选参数。与C#4一样,您可以使用=指定默认值。例如:

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

对于您不想传递的参数,请将它们设置为null,或者根本不将它们添加到cmd.Parameters。它们将在存储过程中具有默认值

答案 2 :(得分:5)

SQLServer允许您将TABLE参数传递给存储过程。因此,您可以定义表类型CREATE TYPE LIST_OF_IDS AS TABLE (id int not null primary key),更改您的过程以接受此类型的变量(它应该只读)。

答案 3 :(得分:2)

您是否考虑过将dictionary用于此目的? 它允许您将任意数量的参数作为键值对传递。 然后你只需要浏览字典并将这些参数添加到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
}

在存储过程本身中,您需要指定参数的默认值。

CREATE PROCEDURE DoStuff(
     @id INT = NULL,
     @value INT = NULL,
     -- the list of parameters with their default values goes here
     )
AS
-- procedure body

答案 4 :(得分:0)

这是一个代码段,它将基于,的字符串拆分为分隔符。您甚至可以参数化逗号。它在没有String_split功能的系统上很有用:

  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

答案 5 :(得分:-1)

如果您具有Sql Server 2008或更高版本,则可以使用表值参数...

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