我们需要生成SSRS报告,我们需要将多值字符串和整数参数转换为datatable并将其传递给存储过程。存储过程包含多个表类型参数。之前我们使用varchar(8000)
,但它也超过了数据类型限制。然后我们考虑引入数据表概念。但我们不知道如何从SSRS传递值。
我们在Using Table-Valued Parameters With SQL Server Reporting Services上找到了GruffCode的解决方案。
解决方案解决了我的问题,我们能够生成报告。但是,有时SSRS会返回以下两个错误:
报告处理期间发生错误 数据集“DSOutput”的查询执行失败 字符串或二进制数据将被截断。声明已经终止。
并且
报告处理中发生意外错误 抛出了'System.OutOfMemoryException'类型的异常。
我不确定导致问题的时间和地点。
答案 0 :(得分:2)
该博客文章中概述的方法依赖于在内存中构建一个巨大的字符串,以便将所有选定的参数值加载到表值参数实例中。如果要选择要传递给查询的大量值,我可能会在尝试构建包含将加载参数的insert语句的字符串时看到它可能导致'System.OutOfMemoryException'。
至于'字符串或二进制数据会被截断'错误,听起来像是在报告用来收集数据的查询或存储过程中产生的。没有看到那个t-sql看起来像什么我不能说为什么会发生这种情况,但我猜它也与选择非常多的参数值有关。
不幸的是,除了试图找出一种方法来选择更少的参数值之外,我不确定是否有解决方法。这里有几个粗略的想法:
答案 1 :(得分:0)
我不喜欢在SQL语句中使用Text参数和EXEC,就像您引用的文章所描述的那样,这样做会受到SQL注入的影响。当查询发送到SQL Server时,带有Multi-value参数的默认SSRS行为会直接替换以逗号分隔的值列表来代替参数。这适用于简单的IN查询,但在其他地方可能不合适。通过将DataSet上的参数值设置为=Join(Parameters!CustomerIDs.Value, ", ")
的表达式,可以绕过此行为。完成后,您可以使用以下SQL获取表变量:
DECLARE @CustomerIDsTable TABLE (CustomerID int NOT NULL PRIMARY KEY)
INSERT INTO @CustomerIDsTable (CustomerID)
SELECT DISTINCT TextNodes.Node.value(N'.', N'int') AS CustomerID
FROM (
SELECT CONVERT(XML, N'<A>' + COALESCE(N'<e>' + REPLACE(@CustomerIDs, N',', N'</e><e>') + N'</e>', '') + N'</A>') AS pNode
) AS xmlDocs
CROSS APPLY pNode.nodes(N'/A/e') AS TextNodes(Node)
-- Do whatever with the resulting table variable, i.e.,
EXEC rpt_CustomerTransactionSummary @StartDate, @EndDate, @CustomerIDsTable
如果使用文本而不是整数,则会改变几行:
DECLARE @CustomerIDsTable TABLE (CustomerID nvarchar(MAX) NOT NULL PRIMARY KEY)
INSERT INTO @CustomerIDsTable (CustomerID)
SELECT DISTINCT TextNodes.Node.value(N'.', N'nvarchar(MAX)') AS CustomerID
FROM (
SELECT CONVERT(XML, N'<A>' + COALESCE(N'<e>' + REPLACE(@CustomerIDs, N',', N'</e><e>') + N'</e>', '') + N'</A>') AS pNode
) AS xmlDocs
CROSS APPLY pNode.nodes(N'/A/e') AS TextNodes(Node)
-- Do whatever with the resulting table variable, i.e.,
EXEC rpt_CustomerTransactionSummary @StartDate, @EndDate, @CustomerIDsTable
此方法也适用于处理用户输入的逗号分隔项字符串。