【问题标题】:Multi-value parameters in stored procedure return errors when multiple values are passed to them存储过程中的多值参数在传递多个值时返回错误
【发布时间】:2019-04-09 19:13:13
【问题描述】:

我正在创建一个使用两个多值参数的存储过程:

@Class AS VARCHAR(5),
@Service AS VARCHAR(5)
(…)    
WHERE B.UTRCLS IN (@Class) AND B.UTSVC IN (@Service)

当两个参数只包含一个值时,该过程可以正常工作。但是,当其中一个或两个都使用多个值时,会引发错误。

在报告生成器中,错误如下:

无法读取数据集 DataSet1 的下一个数据行 (rsErrorReadingNextDataRow)

在 SQL Server 中,错误显示如下(长度被截断):

无法执行查询“SELECT Col1009、Col1010、Col1008、Expr1003、Expr1004 来自(选择 Col1009,Tbl1001.UTCSNM Col1008,Col1010,SUM(Col1016) Expr1003,SUM(Col1014) Expr1004 FROM (…)

我不认为我在声明参数时做错了什么。这是存储过程中多值参数的问题吗?

【问题讨论】:

  • @Class 被定义为varchar(5);那永远不会持有多个值。对于 SP,如果你想传递多个值,你会(通常)使用用户定义的表值数据类型
  • 参数不像你想象的那样工作。存储过程参数始终是单值的。如果 UTSVC 是一个 int 列,并且您尝试将字符串 '1, 2' 传递给参数 @Service,那么 SQL Server 将简单地抱怨 '1, 2' 不能转换为(单个)整数值
  • 有很多关于在SSRS中使用多值参数和存储过程源的教程。在幕后,SSRS 将创建一个包含所选值的 CSV 列表的单个字符串,并将其传递给您的过程。 One example

标签: sql-server reportbuilder3.0 sql-server-2017


【解决方案1】:

您需要使用动态查询:

SET @sqlCommand = 'SELECT * FROM yourTable B WHERE B.UTRCLS IN ( +' @Class + ')' +
                  ' AND B.UTSVC IN (' + @Service +' )'

EXECUTE sp_executesql @sqlCommand

【讨论】:

  • 请删除它,否则人们将开始编写对 SQL 注入开放的代码。
  • 就像你说的停止给人们刀,这样他们就不会互相刺伤。如果你知道来源是好的动态查询就可以了。
  • 我不反对动态 SQL。我反对不安全的动态 SQL。没有办法确保来源是正确的。还有许多其他选项可以解决这个问题,而不会涉及丢失整个服务器的风险。
【解决方案2】:

您帖子中的 cmets 走在正确的轨道上。对于存储过程调用的范围,参数是单值的,而不是对参数值集进行迭代。如果您想将许多值传递给这些参数,我认为您有 2 个选项。

第一个是扩展参数的字符长度并合并分隔符来分割值。然后,您的存储过程代码将需要解析这些值并从那里为每个值执行所需的操作。 STRING_SPLIT() 函数将在此过程中为您提供帮助。

第二个选项是定义一个用户数据类型表类型,它反映了你需要传入参数的多值的数据结构。在您的存储过程调用中,您将定义一个这种类型的变量,用值填充它,然后将该变量传递给您的存储过程。请注意,这样做时必须将它们设置为只读。

用于创建用户类型的 MSDN 链接:https://docs.microsoft.com/en-us/sql/t-sql/statements/create-type-transact-sql?view=sql-server-2017

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-12
    • 1970-01-01
    • 2023-03-14
    • 2011-04-17
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多