使用存储过程的SSRS多值参数

时间:2009-08-10 20:04:55

标签: reporting-services

我正在制作一份SSRS报告,该报告使用包含一些参数的存储过程。我遇到两个参数有问题,因为我想选择多个项目。

这是我所拥有的精简版本:

CREATE PROCEDURE [dbo].[uspMyStoredProcedure] 
  (@ReportProductSalesGroupID AS VARCHAR(MAX) 
  ,@ReportProductFamilyID AS VARCHAR(MAX)
  ,@ReportStartDate AS DATETIME
  ,@ReportEndDate AS DATETIME)

--THE REST OF MY QUERY HERE WHICH PULLS ALL OF THE NEEDED COLUMNS

WHERE DateInvoicedID BETWEEN @ReportStartDate AND @ReportEndDate
AND ProductSalesGroupID IN (@ReportProductSalesGroupID)
AND ProductFamilyID IN (@ReportProductFamilyID)

当我尝试只运行存储过程时,如果我只输入@ReportProductSalesGroupID的1个值和1个值@ReportProductFamilyID,则只返回值。如果我尝试输入两个SalesGroupID和/或2 ProductFamilyID,则不会出错,但我什么都不返回。

-- Returns data
EXEC uspMyStoredProcedure 'G23',     'NOF',     '7/1/2009', '7/31/2009'

-- Doesn't return data
EXEC uspMyStoredProcedure 'G23,G22', 'NOF,ALT', '7/1/2009', '7/31/2009'

在SSRS中,我收到一条错误消息:

  

','

附近的语法不正确

似乎,分隔符包含在字符串中而不是分隔符

5 个答案:

答案 0 :(得分:37)

你需要三件事:

  1. 在SSRS数据集属性中,将多值param作为逗号分隔的字符串传递给存储过程

    =Join(Parameters!TerritoryMulti.Value, ",")
    
  2. 在Sql Server中,您需要一个表值函数,它可以将逗号分隔的字符串拆分为迷你表(例如see here)。编辑:自SQL Server 2016起,您可以使用内置函数STRING_SPLIT来实现此

  3. 在存储过程中,有一个where子句,如下所示:

    WHERE sometable.TerritoryID in (select Item from dbo.ufnSplit(@TerritoryMulti,','))
    

    ...其中ufnSplit是您在步骤2中的拆分功能。

  4. (我的博文中的完整步骤和代码' SSRS multi-value parameters with less fail'):

答案 1 :(得分:6)

我们假设您有一个多值列表@param1

在名为@param2的SSRS报告上创建另一个内部参数,并将默认值设置为:

=Join(Parameters!param1.value, 'XXX')

XXX可以是您想要的任何分隔符,除了逗号(见下文)

然后,您可以将@param2传递给您的查询或存储过程。

如果您尝试以任何其他方式执行此操作,则会导致使用逗号分隔参数的任何字符串函数失败。 (例如CHARINDEX,REPLACE)。

例如Replace(@param2, ',', 'replacement')无效。最终会出现“替换函数需要3个参数”之类的错误。

答案 2 :(得分:1)

最后,我能够为这个问题找到一个简单的解决方案。下面我提供了我遵循的所有(3)步骤。

我希望你们会喜欢它:)

步骤1 - 我创建了一个包含一列的全局临时表。

CREATE GLOBAL TEMPORARY TABLE TEMP_PARAM_TABLE(
  COL_NAME  VARCHAR2(255 BYTE)
) ON COMMIT PRESERVE ROWS NOCACHE;

步骤2 - 在拆分过程中,我没有使用任何数组或数据表,我已经将拆分值直接加载到我的全局临时表中。

CREATE OR REPLACE PROCEDURE split_param(p_string IN VARCHAR2 ,p_separator IN VARCHAR2
)
IS
   v_string VARCHAR2(4000);
   v_initial_pos NUMBER(9) := 1;
   v_position NUMBER(9) := 1;
BEGIN
   v_string := p_string || p_separator;

   delete from temp_param_policy;

   LOOP
      v_position :=
                  INSTR(v_string, p_separator, v_initial_pos, 1);
      EXIT WHEN(NVL(v_position, 0) = 0);

      INSERT INTO temp_param_table
           VALUES (SUBSTR(v_string, v_initial_pos
                         , v_position - v_initial_pos));

      v_initial_pos := v_position + 1;
   END LOOP;
commit;

END split_param;
/

步骤3 - 在SSRS数据集参数中,我使用了

=Join(Parameters!A_COUNTRY.Value, ",")

步骤4:在存储过程开始时执行过程

Exec split_param(A_Country, ‘,’);

步骤5:在你的存储过程中,sql使用如下所示的条件。

Where country_name in (select * from TEMP_PARAM_TABLE)

答案 3 :(得分:0)

当SSRS传递参数时,它的格式为:Param1,Param2,Param3。

在该过程中,您只需要在每个参数周围放置标识符。以及数据集返回的值周围的标识符。就我而言,我使用了分号。

CREATE OR REPLACE PROCEDURE user.parameter_name ( i_multivalue_parameter ) AS l_multivalue_parameter varchar2(25555) := ';' || replace(i_multivalue_parameter,',',';') || ';'; BEGIN select something from dual where ( instr(l_multivalue_parameter, ';' || database_value_that_is_singular || ';') > 0 ) END;

i_multivalue_parameter通过SSRS传入。

l_multivalue_parameter读取通过SSRS传入的参数,并在每个值周围放置标识符。

database_value_that_is_singular是为每条记录返回的值。

因此,如果' Type1,Type2,Type3'是通过SSRS传递的:

i_multivalue_parameter是:Type1,Type2,Type3

l_multivalue_parameter是:; Type1; Type2; Type3;

database_value_that_is_singular是:; Type1;或; Type2;或; Type3;

如果参数匹配,Instr将返回一个大于0的值。

即使每个参数都相似,这也有效。 EG:" A型和#34;和"类型AA"。那是" A型"不匹配"输入AA"。

答案 4 :(得分:0)

我找到了解决问题的简单方法。在报告中将参数值定义为这样的表达式

="'" + Join(Parameters!parm.Value,"','") + "'"

(以防万一您不能读懂它的第一个和最后一个文字是双引号,单引号,双引号。连接文字是双引号,单引号,逗号,单引号,双引号)

然后在存储过程中,可以使用动态sql创建语句。我这样做是为了创建一个临时值表,以便在以后的查询中加入该值,像这样:

CREATE #nametable (name nvarchar(64))

SET @sql = N'SELECT Name from realtable where name in (' + @namelist + ')'

INSERT INTO #nametable exec sp_executesql @sql

@namelist是存储过程参数的名称。