繁体   English   中英

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

[英]Stored procedure with variable number of parameters

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

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

谁能帮助我如何在存储过程中传递这些可变数量的参数? 谢谢

您可以将它作为逗号分隔的列表传入,然后使用拆分函数,并根据结果进行连接。

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

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

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

对于不想传递的参数,要么将它们设置为null ,要么根本不将它们添加到cmd.Parameters中。 它们将在存储过程中使用默认值

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

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

这是一个基于,作为分隔符分割字符串的代码片段。 您甚至可以参数化逗号。 它在还没有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

您可以执行此操作的另一种方法是将 arguments 序列化为 JSON 字符串并将其传递到您的存储过程中。 您可以使用 NewtonSoft.JSON package 执行以下操作: string json = JsonConvert.SerializeObject(obj); 并将json var 传递到您的过程中。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM