【问题标题】:Passing multiple values for a single parameter in Reporting Services在 Reporting Services 中为单个参数传递多个值
【发布时间】:2010-10-05 10:55:43
【问题描述】:

我的报告中有几个多选参数。我正在尝试找到一种方法来为 Web 查询字符串中的单个参数传递多个值?如果我传入一个值,它就可以正常工作。

报告运行良好,可以为单个参数选择多个选项。我的麻烦在于网络查询字符串。

【问题讨论】:

标签: sql reporting-services parameters query-string


【解决方案1】:

从 MSSQL 2016 开始 - 兼容级别为 130,您可以利用 String_Split() 从 SSRS 解析您的连接参数。假设您想从 SSRS 中的查询中填充参数,然后将该参数传递给存储的过程或 SSRS 共享数据集:

  1. 将两个数据集添加到您的 SSRS 报告中,一个返回要在参数中显示的值和标签列表,另一个包含您要过滤的实际数据。这些数据集中的每一个都可以是存储过程或共享数据集或嵌入式查询。
  2. 在 SSRS 中创建一个不在您要过滤的数据集上的参数。我们就叫它Customer
  3. 设置Customer 参数以允许多个值,并设置Available Values 选项卡,其中包含要从查询中显示的数据集、标签和值。
  4. 右键单击要过滤的数据集并添加在存储过程中定义的参数。我们就叫它CustomerList吧。
  5. 单击此参数值字段旁边的表达式按钮并执行Join(Parameters!Customer.Value, ",")
  6. 在您存储的过程或共享数据集中,利用 string_split 将逗号分隔的 @CustomerList 参数分解为一个数组: Customer.CustID in (select value from string_split(@CustomerList, ',') where value = Customer.CustID)

【讨论】:

    【解决方案2】:

    以下解决方案对我有用。

    1. 在数据集属性的参数选项卡中,单击您需要允许逗号分隔输入的参数旁边的表达式图标 (!http://chittagongit.com//images/fx-icon/fx-icon-16.jpg [fx 符号])。

    2. 在出现的表达式窗口中,使用拆分函数(通用函数 -> 文本)。示例如下:

    =Split(Parameters!ParameterName.Value,",")

    【讨论】:

      【解决方案3】:

      这适用于一组不同的字符串(例如“START”、“END”、“ERROR”、“SUCCESS”)

      1)定义一个报告参数(例如@log_status)并勾选“允许多个值”

      2) 定义数据集
      3) 打开数据集属性窗口
      3a) 在查询选项卡中输入您的查询:例如

      select * from your_table where (CHARINDEX(your_column, @log_status,0) > 0)
      

      3b) 在参数选项卡中输入您的参数,例如
      Parametername: @log_status ; Parametervalue: <<Expr>>
      3c) 对于 Expr,单击“fx”按钮并输入:

      =join(Parameters!log_status.Value,",")
      

      完成! (它类似于 Ed Harper 的解决方案,但很抱歉这对我不起作用)

      【讨论】:

        【解决方案4】:

        我需要 Oracle 解决方案,我发现这在我的 DB>=10g 报告查询中对我有用。

        select * from where in ( 从对偶中选择 regexp_substr(,'[^,]+', 1, level) connect by regexp_substr(, '[^,]+', 1, level) is not null );

        来源 https://blogs.oracle.com/aramamoo/entry/how_to_split_comma_separated_string_and_pass_to_in_clause_of_select_statement

        【讨论】:

          【解决方案5】:

          因此,在查询中乘以文本值最终会在我使用的每个值周围加上单引号 =join(Parameters!Customer.Value,"','")。所以在“.Value”之后就是逗号,双引号,单引号,逗号,单引号,双引号,右括号。简单:)

          【讨论】:

            【解决方案6】:

            首先将多个值添加到表中可能会更容易,然后您可以加入或任何您想要的(即使使用通配符)或将数据保存到另一个表以供以后使用(甚至将值添加到另一个表)。

            通过数据集中的表达式设置参数值:

            ="SELECT DISTINCT * FROM (VALUES('" & JOIN(Parameters!SearchValue.Value, "'),('") & "')) 
            AS tbl(Value)"
            

            查询本身:

            DECLARE @Table AS TABLE (Value nvarchar(max))
            
            INSERT INTO @Table EXEC sp_executeSQL @SearchValue 
            

            通配符示例:

            SELECT * FROM YOUR_TABLE yt 
            
            INNER JOIN @Table rt ON yt.[Join_Value] LIKE '%' + rt.[Value] + '%'
            

            我很想找到一种无需动态 SQL 的方法,但由于 SSRS 将参数传递给实际查询的方式,我认为它不会起作用。如果有人知道更好,请告诉我。

            【讨论】:

              【解决方案7】:

              这对我很有用:

              WHERE CHARINDEX(CONVERT(nvarchar, CustNum), @CustNum) > 0
              

              【讨论】:

              • 我很难拼凑出这如何回答这个问题。你能详细说明一下吗?
              【解决方案8】:
              1. 为报表中的列表创建数据集
              2. 右键单击参数并选择可用值
              3. 选择新创建的数据集作为数据集
              4. 将传递给存储过程的值作为值字段添加
              5. 将参数描述添加到标签字段(如果参数是 customerID,则标签可以是 CustomerName ex.)
              6. 最后,将以下代码添加到您的存储过程中

              将@paramName 声明为 NVARCHAR(500),

              IF RIGHT(@paramName, 1) = ',' 开始 SET @paramName = LEFT((@paramName, LEN((@paramName)-1) 结束

              【讨论】:

                【解决方案9】:

                这是关于使用连接函数保存多值参数,然后稍后从数据库中恢复完全相同的选择。

                我刚做完一个要求必须保存参数的报表,当再次打开报表时(报表传递一个OrderID参数),必须再次选择用户之前选择的值。

                该报告使用了六个参数,每个参数都有自己的数据集和生成的下拉列表。这些参数依赖于先前的参数来缩小最终选择的范围,并且在“查看”报告时调用存储过程来填充。

                存储过程接收从报告中传递给它的每个参数。它检查数据库中的存储表以查看是否为该 OrderID 保存了任何参数。如果没有,则保存所有参数。如果是这样,它会更新该订单的所有参数(这是用户稍后改变主意的情况)。

                当报表运行时,有一个数据集 dsParameters,它是一个 SQL 文本,它会输出并选择该 orderID 的单行(如果有的话)。报表中的每个参数都从该数据集中获取其默认值,并从专用于该参数的数据集中获取其选择列表。

                我遇到了多选参数的问题。我在主数据集参数列表中使用了 join(@Value,",") 命令,将逗号分隔的字符串传递给存储过程。但是如何恢复呢?您不能将逗号分隔的字符串反馈回参数的默认值框。

                我必须创建另一个数据集来拆分参数,其方式类似于您所说的。它看起来像这样:

                IF OBJECT_ID('tempdb..#Parse','U') IS NOT NULL DROP TABLE #Parse
                
                DECLARE @Start int, @End int, @Desc varchar(255)
                
                SELECT @Desc = fldDesc FROM dbCustomData.dbo.tblDirectReferralFormParameters WHERE fldFrom = @From and fldOrderID = @OrderID
                
                CREATE TABLE #Parse (fldDesc varchar(255))
                
                SELECT @Start = 1, @End = 1
                
                WHILE @End > 0
                    BEGIN
                        SET @End = CHARINDEX(',',@Desc,@Start)
                        IF @End = 0 
                            BEGIN
                                INSERT #Parse SELECT REPLACE(SUBSTRING(@Desc,@Start,LEN(@Desc)),',','') AS fldDesc 
                                BREAK
                            END
                        ELSE        
                            BEGIN
                                INSERT #Parse SELECT REPLACE(SUBSTRING(@Desc,@Start,@End-@Start),',','') AS fldDesc 
                            END
                        SET @Start = @End + 1
                    END
                
                SELECT * FROM #Parse
                

                每次打开表单时,此数据集都会检查数据库中是否存在此多值参数的已保存字符串。如果没有,则返回 null。如果打开,它会解析逗号并为每个值创建一行。

                然后将默认值框设置为此数据集,fldDesc。有用!当我选择一个或多个时,它们会在再次打开表单时保存并补充。

                我希望这会有所帮助。我搜索了一段时间,没有发现任何提及将连接字符串保存在数据库中,然后将其解析到数据集中。

                【讨论】:

                  【解决方案10】:

                  这是我在将多选参数传递给另一个多选参数时使用的。

                  =SPLIT(JOIN(Parameters!<your param name>.Value,","),",")
                  

                  【讨论】:

                  • 这是我最终不得不使用的。单独拆分不起作用,单独的Join只传递了多选中的第一个参数。 +1 谢谢 Minks!
                  • 太棒了!!谢谢
                  • 如果您忘记将参数设置为“允许多个值”,请设置它:)
                  【解决方案11】:

                  过去,我使用存储过程和函数在 SQL Server 查询中为报告服务选择多年。按照 Ed Harper 的建议在查询参数值中使用 Join 表达式,仍然无法在 where 语句中使用 SQL IN 子句。我的解决方案是在 where 子句中使用以下内容以及参数 Join 表达式: 和 charindex (cast(Schl.Invt_Yr as char(4)) , @Invt_Yr) > 0

                  【讨论】:

                    【解决方案12】:

                    我是该网站的新手,不知道如何评论以前的答案,我觉得这应该是。我也无法投票给 Jeff 的帖子,我相信这给了我答案。总之……

                    虽然我可以看到一些出色的帖子和后续调整是如何工作的,但我只有对数据库的读取权限,因此没有 UDF、SP 或基于视图的解决方案适合我。所以 Ed Harper 的解决方案看起来不错,除了 VenkateswarluAvula 的评论,您不能将逗号分隔的字符串作为参数传递给 WHERE IN 子句并期望它按您的需要工作。但 Jeff 的 ORACLE 10g 解决方案填补了这一空白。我将这些与 Russell Christopher 在http://blogs.msdn.com/b/bimusings/archive/2007/05/07/how-do-you-set-select-all-as-the-default-for-multi-value-parameters-in-reporting-services.aspx 的博客文章放在一起,我有我的解决方案:

                    使用可用值的任何来源(可能是数据集)创建多选参数 MYPARAMETER。就我而言,多选来自一堆 TEXT 条目,但我确信通过一些调整它可以与其他类型一起使用。如果您希望全选为默认位置,请将相同的源设置为默认位置。这为您提供了您的用户界面,但创建的参数不是传递给我的 SQL 的参数。

                    跳到 SQL 和 Jeff 对 WHERE IN (@MYPARAMETER) 问题的解决方案,我自己有一个问题,其中 1 个值 ('Charge') 出现在其他值之一 (' Non Charge'),这意味着 CHARINDEX 可能会发现误报。我需要在参数之前和之后搜索分隔值。这意味着我需要确保逗号分隔的列表也有前导和尾随逗号。这是我的 SQL sn-p:

                    where ...
                    and CHARINDEX(',' + pitran.LINEPROPERTYID + ',', @MYPARAMETER_LIST) > 0
                    

                    中间的部分是创建另一个参数(在生产中隐藏,但在开发时不会):

                    • MYPARAMETER_LIST 的名称
                    • 一种文字
                    • 单个可用值="," + join(Parameters!MYPARAMETER.Value,",") + "," 和一个标签
                      没关系(因为它不会显示)。
                    • 默认值完全相同
                    • 为了确定,我在两个参数的“高级”中都设置了“始终刷新” 属性

                    传递给 SQL 的正是这个参数,它恰好是一个可搜索的字符串,但 SQL 处理它的方式与任何一段文本一样。

                    我希望将这些答案片段放在一起可以帮助人们找到他们正在寻找的东西。

                    【讨论】:

                      【解决方案13】:

                      您还可以在存储过程中添加此代码:

                      set @s = char(39) + replace(@s, ',', char(39) + ',' + char(39)) + char(39)
                      

                      (假设@s 是一个多值字符串(如“A,B,C”))

                      【讨论】:

                        【解决方案14】:

                        我在使用原本很棒的 fn_MVParam 时遇到了问题。 SSRS 2005 发送的数据带有撇号作为 2 个引号。

                        我添加了一行来解决这个问题。

                        select @RepParam = replace(@RepParam,'''''','''')
                        

                        我的 fn 版本也使用 varchar 而不是 nvarchar。

                        CREATE FUNCTION [dbo].[fn_MVParam]
                           (
                            @RepParam varchar(MAX),
                            @Delim char(1)= ','
                           )
                        RETURNS @Values TABLE (Param varchar(MAX)) AS
                        /*
                          Usage:  Use this in your report SP 
                             where ID in (SELECT Param FROM fn_MVParam(@PlanIDList,','))
                        */
                        
                        BEGIN
                        
                           select @RepParam = replace(@RepParam,'''''','''')
                           DECLARE @chrind INT
                           DECLARE @Piece varchar(MAX)
                           SELECT @chrind = 1
                           WHILE @chrind > 0
                              BEGIN
                                 SELECT @chrind = CHARINDEX(@Delim,@RepParam)
                                 IF @chrind > 0
                                    SELECT @Piece = LEFT(@RepParam,@chrind - 1)
                                 ELSE
                                    SELECT @Piece = @RepParam
                                 INSERT @VALUES(Param) VALUES(@Piece)
                                 SELECT @RepParam = RIGHT(@RepParam,DATALENGTH(@RepParam) - @chrind)
                                 IF DATALENGTH(@RepParam) = 0 BREAK
                              END
                           RETURN
                        END
                        

                        【讨论】:

                          【解决方案15】:

                          如果您想通过查询字符串将多个值传递给 RS,您只需为每个值重复报告参数即可。

                          例如;我有一个名为 COLS 的 RS 列,该列需要一个或多个值。

                          &rp:COLS=1&rp:COLS=1&rp:COLS=5 etc..
                          

                          【讨论】:

                            【解决方案16】:

                            修改伟大的约翰解决方案,解决:

                            • “2 个引号”错误
                            • 参数中的一个后的空格

                              ALTER FUNCTION [dbo].[fn_MVParam] (@RepParam nvarchar(4000), @Delim char(1)= ',') RETURNS @Values TABLE (Param nvarchar(4000))AS BEGIN //2 quotes error set @RepParam = replace(@RepParam,char(39)+char(39),CHAR(39)) DECLARE @chrind INT DECLARE @Piece nvarchar(100) SELECT @chrind = 1 WHILE @chrind > 0 BEGIN SELECT @chrind = CHARINDEX(@Delim,@RepParam) IF @chrind > 0 SELECT @Piece = LEFT(@RepParam,@chrind - 1) ELSE SELECT @Piece = @RepParam INSERT @Values(Param) VALUES(CAST(@Piece AS VARCHAR(300))) //space after one of piece in parameter: LEN(@RepParam + '1')-1 SELECT @RepParam = RIGHT(@RepParam,LEN(@RepParam + '1')-1 - @chrind) IF LEN(@RepParam) = 0 BREAK END RETURN END

                            【讨论】:

                              【解决方案17】:

                              这是 SQL Reporting Services 中支持较差的功能之一。

                              您需要做的是将所有选定的项目作为单个字符串传递给您的存储过程。字符串中的每个元素都将用逗号分隔。

                              然后我要做的是使用将提供的字符串作为表格返回的函数来拆分字符串。见下文。

                              ALTER FUNCTION [dbo].[fn_MVParam]
                                 (@RepParam nvarchar(4000), @Delim char(1)= ',')
                              RETURNS @Values TABLE (Param nvarchar(4000))AS
                                BEGIN
                                DECLARE @chrind INT
                                DECLARE @Piece nvarchar(100)
                                SELECT @chrind = 1 
                                WHILE @chrind > 0
                                  BEGIN
                                    SELECT @chrind = CHARINDEX(@Delim,@RepParam)
                                    IF @chrind  > 0
                                      SELECT @Piece = LEFT(@RepParam,@chrind - 1)
                                    ELSE
                                      SELECT @Piece = @RepParam
                                    INSERT  @Values(Param) VALUES(CAST(@Piece AS VARCHAR))
                                    SELECT @RepParam = RIGHT(@RepParam,LEN(@RepParam) - @chrind)
                                    IF LEN(@RepParam) = 0 BREAK
                                  END
                                RETURN
                                END
                              

                              然后您可以在主查询的 where 子句中引用结果,如下所示:

                              where someColumn IN(SELECT Param FROM dbo.fn_MVParam(@sParameterString,','))
                              

                              我希望您发现此解决方案有用。请随时提出您可能有的任何问题。

                              干杯,约翰

                              【讨论】:

                              • 谢谢。使用 nvarchar(max) 来消除长度限制怎么样?
                              • 如何“将所有选定的项目作为单个字符串传递给存储过程”?感谢您的帮助
                              • 工作就像一个魅力!谢谢。一直在搜索几个小时。
                              【解决方案18】:

                              John Sansom 和 Ed Harper 有很好的解决方案。但是,在处理 ID 字段(即整数)时,我无法让它们工作。我修改了下面的拆分函数,将值转换为整数,以便表将与主键列连接。我还注释了代码并添加了一个顺序列,以防分隔列表顺序很重要。

                              CREATE FUNCTION [dbo].[fn_SplitInt]
                              (
                                  @List       nvarchar(4000),
                                  @Delimiter  char(1)= ','
                              )
                              RETURNS @Values TABLE
                              (
                                  Position int IDENTITY PRIMARY KEY,
                                  Number int
                              )
                              
                              AS
                              
                                BEGIN
                              
                                -- set up working variables
                                DECLARE @Index INT
                                DECLARE @ItemValue nvarchar(100)
                                SELECT @Index = 1 
                              
                                -- iterate until we have no more characters to work with
                                WHILE @Index > 0
                              
                                  BEGIN
                              
                                    -- find first delimiter
                                    SELECT @Index = CHARINDEX(@Delimiter,@List)
                              
                                    -- extract the item value
                                    IF @Index  > 0     -- if found, take the value left of the delimiter
                                      SELECT @ItemValue = LEFT(@List,@Index - 1)
                                    ELSE               -- if none, take the remainder as the last value
                                      SELECT @ItemValue = @List
                              
                                    -- insert the value into our new table
                                    INSERT INTO @Values (Number) VALUES (CAST(@ItemValue AS int))
                              
                                    -- remove the found item from the working list
                                    SELECT @List = RIGHT(@List,LEN(@List) - @Index)
                              
                                    -- if list is empty, we are done
                                    IF LEN(@List) = 0 BREAK
                              
                                  END
                              
                                RETURN
                              
                                END
                              

                              如前所述使用此函数:

                              WHERE id IN (SELECT Number FROM dbo.fn_SplitInt(@sParameterString,','))
                              

                              【讨论】:

                                【解决方案19】:

                                甲骨文:

                                “IN”短语(Ed 的解决方案)不适用于 Oracle 连接(至少版本 10)。但是,发现了这个简单的解决方法。使用数据集的参数选项卡将多值参数转换为 CSV:

                                    :name =join(Parameters!name.Value,",")
                                

                                然后在你的 SQL 语句的 WHERE 子句中使用 instring 函数来检查匹配。

                                    INSTR(:name, TABLE.FILENAME) > 0
                                

                                【讨论】:

                                • 不错。下次我对该报告进行维护时,我会试一试。
                                • 谢谢杰夫。这个问题在 11G 中似乎仍然存在。
                                【解决方案20】:

                                只是一个评论 - 我遇到了一个痛苦的世界,试图让一个 IN 子句在与 Oracle 10g 的连接中工作。我认为重写后的查询不能正确传递给 10g db。我不得不完全放弃多值。查询仅在选择单个值(来自多值参数选择器)时才会返回数据。我尝试了 MS 和 Oracle 驱动程序,结果相同。我很想知道是否有人在这方面取得了成功。

                                【讨论】:

                                • 我感受到你的痛苦。在最终找到一个非常简单的解决方案之前,我自己花了一天的大部分时间来解决这个问题。如果您仍然感兴趣,我已经在这里发布了答案。
                                【解决方案21】:

                                虽然 John Sansom 的解决方案有效,但还有另一种方法可以做到这一点,而不必使用可能效率低下的标量值 UDF。 在 SSRS 报告中,在查询定义的参数选项卡上,将参数值设置为

                                =join(Parameters!<your param name>.Value,",")
                                

                                在您的查询中,您可以像这样引用该值:

                                where yourColumn in (@<your param name>)
                                

                                【讨论】:

                                • @Adel - 是 - UDF = 用户定义函数
                                • @VenkateswarluAvula - 你有不同的问题; SQL Server 不支持以这种方式将多个值传递给IN 子句。实际上有数百个问题涉及这个主题 - 请参阅stackoverflow.com/…
                                • @tsqln00b - 我不再有权访问 SSRS 2005 环境来测试这个,但根据 CodeGrue 对此线程的回答,使用任何 int 类型的解决方案可能会出现问题
                                • 我想补充一点,在 SSRS 2008R2 中不需要使用JOIN。您可以设置参数值就像Parameters!&lt;your param name&gt;.Value
                                • 这种方法无法按预期工作。如果将参数传递给 Customer 为“Steve,Dave,Bill”的存储过程,那么这将与 Customer 为“Steve”或“Dave”或“Bill”的行不匹配。它只会匹配 Customer 正好是“Steve,Dave,Bill”的行。
                                猜你喜欢
                                • 1970-01-01
                                • 1970-01-01
                                • 2013-10-12
                                • 2012-10-27
                                • 2017-07-18
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                相关资源
                                最近更新 更多