在SSRS中,我有一个办公室管理员名称参数,由存储过程填充:
SELECT
MANAGER.office_manager_name
FROM (SELECT
ISNULL(REPLACE(PRACT_LOC.officemanagername, ',', ''), '*N/A') AS office_manager_name
FROM PRACTICELOCATIONS PRACT_LOC
UNION
SELECT
'*N/A') MANAGER
ORDER BY
MANAGER.office_manager_name
参数填充如下:
*N/A, Smith John, Sharp Alex, O'Toole Tom
在SQL Server中,我有另一个SP,它使用函数分割器从表中连接office manager名称:
CREATE PROCEDURE IP
(@office_manager_name VARCHAR(4000))
AS
Select * from Table A
where ISNULL(REPLACE(A.officemanagername, ',', ''), '*N/A') IN (SELECT item FROM DBO.FNSPLIT(@officemanagername, ','))
功能拆分器代码如下所示:
ALTER FUNCTION [dbo].[fnSplit]
(
@sInputList VARCHAR(MAX), -- List of delimited items
@sDelimiter VARCHAR(MAX) = ',' -- delimiter that separates items
)
RETURNS @List TABLE (item VARCHAR(MAX))
BEGIN
DECLARE @sItem VARCHAR(MAX)
WHILE CHARINDEX(@sDelimiter,@sInputList,0) <> 0
BEGIN
SELECT
@sItem=RTRIM(LTRIM(SUBSTRING(@sInputList,1,CHARINDEX (@sDelimiter,@sInputList,0)-1))),
@sInputList=RTRIM(LTRIM(SUBSTRING(@sInputList,CHARINDEX(@sDelimiter,@sInputList,0)+LEN(@sDelimiter),LEN(@sInputList))))
IF LEN(@sItem) > 0
INSERT INTO @List SELECT @sItem
END
IF LEN(@sInputList) > 0
INSERT INTO @List SELECT @sInputList -- Put the last item in
RETURN
END
我遇到的问题是,如果我从参数中选择所有经理,那么办公室经理Tom O'Toole的任何记录都不会显示在报告中。如果我只是从参数列表中选择O'Toole Tom,他确实会出现。我认为这与他的姓氏中的撇号有关,因为他是唯一有撇号的经理。如果是这种情况,是否有人知道如何在此代码中使用转义字符来让O'Toole填充?
答案 0 :(得分:1)
我使用SQL Server Profiler发现了这个问题。 报告发送到服务器的是:
exec rsp_m_initialprocessxxxx @practice_manager=N'*N/A,O''''Toole Tom,Sharp Alex,Smith John'
正如你所看到的那样,而不是2个撇号,它正在发送4:O''''Toole Tom
。
使用DBO.FNSPLIT
分割此sting时,您已O''Toole Tom
而不是O'Toole Tom
,而且您的表中找不到匹配项。
workaroud如下:在你的存储过程中用这样的2替换4个撇号,添加额外的变量@ practice_manager1:
declare @practice_manager1 varchar(4000) = (select replace(@practice_manager, replicate(char(39), 2), replicate(char(39), 1)));
Select * from dbo.A
where ISNULL(REPLACE(A.office_manager_name, ',', ''), '*N/A') IN (SELECT item FROM DBO.FNSPLIT(@practice_manager1, ','));
Char(39)是撇号,我使用它的代码代替符号而不会变得疯狂'''''
P.S。您使用的是SSRS 2016,而非2012年
<强> UPDATE1 强>
我刚试过这个,但它仍然不起作用。如果我,它也行不通 只需选择Tom O'Toole而不是之前有效的All。
我已经为这两种情况再次测试了这段代码,这是我的代表:
declare @t table (test_num int, name varchar(4000));
insert into @t values (1, 'O''Toole Tom'),
(2, '*N/A,O''''Toole Tom,Sharp Alex,Smith John');
SELECT test_num, name, item
FROM @t cross apply DBO.FNSPLIT(name, ',');
SELECT test_num, name, item
FROM @t cross apply DBO.FNSPLIT(replace(name, replicate(char(39), 2), replicate(char(39), 1)), ',');
我为这两种情况插入了2个字符串并直接将DBO.FNSPLIT
应用于这些字符串,并且在制作replace
之后,第二种方式适用于这两种情况:
<强> UPDATE2 强>
如何找到传递给存储过程的第一个参数。
首先改变您的程序,这将使旧计划无效。
然后使用有问题的参数从SSRS运行它。这个参数将被嗅探,因为它是第一次执行。然后,您可以以图形方式或在程序计划的xml中将其视为ParameterCompiledValue
。
以下是从缓存中获取proc计划的代码:
select qp.query_plan
from sys.dm_exec_procedure_stats ps
cross apply sys.dm_exec_query_plan(ps.plan_handle) qp
where object_id = object_id('dbo.sp_test'); -- put here your sp name
答案 1 :(得分:0)
问题是&#34;&#39;&#34;在Ton的名称中的符号,尝试添加替换波纹的代码
REPLACE(@officemanagername,'''','''''')
----
CREATE PROCEDURE ##IP
(@office_manager_name VARCHAR(4000))
AS
Select * from Table A
where ISNULL(REPLACE(A.officemanagername, ',', ''), '*N/A') IN (SELECT item FROM DBO.FNSPLIT(REPLACE(@officemanagername,'''',''''''), ','))
答案 2 :(得分:0)
我的存储过程遇到了同样的问题。
在我的过程REPLACE(@param,'''','''''')
中减少引号是可行的。但是,在SSRS之外调用我的过程不适用于真正的2个单引号。
有一个更好的解决方案。您可以加入报告参数,然后再将其传递给过程:
Join(Parameters!Value.Value, ",")