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

CPD*_*PDS 17 sql sql-server-2008 sql-server-2008-r2

我有存储过程,我必须传递参数,但问题是我不知道有多少参数将来它可以是1,在下一次运行它可以是5.

cmd.Parameters.Add(new SqlParameter("@id", id)
Run Code Online (Sandbox Code Playgroud)

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

Aar*_*and 20

您可以将其作为逗号分隔列表传递,然后使用拆分函数,并对结果进行连接.

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
   );
Run Code Online (Sandbox Code Playgroud)

现在你的存储过程:

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
Run Code Online (Sandbox Code Playgroud)

然后叫它:

EXEC dbo.doStuff @List = '1, 2, 3, ...';
Run Code Online (Sandbox Code Playgroud)

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

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


And*_*mar 6

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

create procedure dbo.doStuff(
     @stuffId int = null, 
     @stuffSubId int = null, 
     ...)
as
...
Run Code Online (Sandbox Code Playgroud)

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


a1e*_*x07 5

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