【问题标题】:Stored procedure with variable number of parameters具有可变参数数量的存储过程
【发布时间】:2011-09-18 15:45:38
【问题描述】:

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

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

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

【问题讨论】:

  • 要传递不同数量的参数,您只需在客户端代码中使用条件逻辑来添加所需的参数,但您的意思是您想知道如何传递不同数量的ids到存储过程?
  • 是的......它类似于将数组传递给存储过程......但这个数组的长度可以变化。
  • 这是什么 RDBMS(包括版本)?

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


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        您是否考虑过为此目的使用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
        

        【讨论】:

        • 这是在 C# 端...我如何在 sql server 端阅读这个...我将如何创建过程?
        • 您可以查看 Andomar 对程序示例的响应。只需添加类似的 sn-p 即可将所有内容放在同一个地方。
        【解决方案5】:

        这是一个代码 sn-p,它根据, 作为分隔符来拆分字符串。您甚至可以参数化逗号。它在还没有 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
        

        【讨论】:

          【解决方案6】:

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

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

          【讨论】:

            猜你喜欢
            • 2010-11-02
            • 2013-08-04
            • 1970-01-01
            • 2011-09-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多