我正在制作一份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中,我收到一条错误消息:
','
附近的语法不正确
似乎,
分隔符包含在字符串中而不是分隔符
答案 0 :(得分:37)
你需要三件事:
在SSRS数据集属性中,将多值param作为逗号分隔的字符串传递给存储过程
=Join(Parameters!TerritoryMulti.Value, ",")
在Sql Server中,您需要一个表值函数,它可以将逗号分隔的字符串拆分为迷你表(例如see here)。编辑:自SQL Server 2016起,您可以使用内置函数STRING_SPLIT
来实现此
在存储过程中,有一个where子句,如下所示:
WHERE sometable.TerritoryID in (select Item from dbo.ufnSplit(@TerritoryMulti,','))
...其中ufnSplit
是您在步骤2中的拆分功能。
(我的博文中的完整步骤和代码' 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
是存储过程参数的名称。