我正在向SSRS构建报告,用户可以在其中手动向4个文本参数添加一些数据,这些数据将被发送到存储过程,该存储过程必须使用它们来创建临时表。
我目前正在创建存储过程之前测试sql脚本,但由于每个值都存储在单独的变量中,因此我无法弄清楚如何将所有数据放入临时表中
我创建了一个函数,将值解析为每个变量并将其用作表,然后将每个变量的insert语句放入同一临时表中,但数据未添加到同一行中,例如,临时表上的第1行应为80605166、190411-001751,Email1,CC1,但不能为
Declare
@TID varchar(max) = '80605166,80414297,80410854'
,@Incident varchar(max) = '190411-001751,190411-001829,190228-000928'
,@Email varchar(max) = 'Email1,Email2,Email3'
,@CC varchar(max) = 'CC1,CC2,CC3'
--Create temp table to storage user input data into paramaters
IF OBJECT_ID ('tempdb..#Paramaters') IS NOT NULL DROP TABLE #Paramaters
CREATE TABLE #Paramaters ( TID INT null , [Incident Number] nvarchar(14)null , Email varchar(500) null , CC varchar(500)null)
INSERT #Paramaters (TID)
select value from RPT.TVF_TextToTable (@TID,',')
INSERT #Paramaters ([Incident Number])
select value from RPT.TVF_TextToTable (@Incident,',')
INSERT #Paramaters (Email)
select value from RPT.TVF_TextToTable (@Email,',')
INSERT #Paramaters (CC)
select value from RPT.TVF_TextToTable (@CC,',')
Select * from #Paramaters
预期产量
第一个TID与第一个事件,第一个电子邮件和第一个CC一起
以下是TVF函数的代码:
ALTER function [RPT].[TVF_TextToTable]
(
@Text varchar(max),
@Delimiter char(1) = ','
)
RETURNS @table TABLE (Value varchar(256))
AS
BEGIN
declare @Length integer
declare @Begin integer
declare @End integer
set @Length = datalength(@Text)
set @Begin = 1
set @End = patindex('%' + @Delimiter + '%', @Text)
while @End <> 0
begin
insert into @table
select substring(@Text, @Begin, @End - 1)
set @Begin = @Begin + @End
set @End = patindex('%' + @Delimiter + '%', substring(@Text, @Begin, @Length - @Begin + 1))
end
-- Now Catch any End Piece when it doesn't end with a comma
if (@Length >= @Begin)
begin
insert into @table
select substring(@Text, @Begin, @Length - @Begin + 1)
end
RETURN
end
答案 0 :(得分:0)
正如大家所指出的那样,您需要在要拆分的值上添加索引号,使用该索引号可以join
一起使用不同的变量输出。此查询使用字符串拆分功能完成了您需要的操作,该字符串拆分功能的执行速度也要比基于while
的循环快很多:
Declare
@TID varchar(max) = '80605166,80414297,80410854'
,@Incident varchar(max) = '190411-001751,190411-001829,190228-000928'
,@Email varchar(max) = 'Email1,Email2,Email3'
,@CC varchar(max) = 'CC1,CC2,CC3';
select s1.item as TID
,s2.item as Incident
,s3.item as Email
,s4.item as CC
from dbo.fn_StringSplit4k(@TID,',',null) as s1
join dbo.fn_StringSplit4k(@Incident,',',null) as s2
on s1.rn = s2.rn
join dbo.fn_StringSplit4k(@Email,',',null) as s3
on s1.rn = s3.rn
join dbo.fn_StringSplit4k(@CC,',',null) as s4
on s1.rn = s4.rn;
+----------+---------------+--------+-----+
| TID | Incident | Email | CC |
+----------+---------------+--------+-----+
| 80605166 | 190411-001751 | Email1 | CC1 |
| 80414297 | 190411-001829 | Email2 | CC2 |
| 80410854 | 190228-000928 | Email3 | CC3 |
+----------+---------------+--------+-----+
create function dbo.fn_StringSplit4k
(
@str nvarchar(4000) = ' ' -- String to split.
,@delimiter as nvarchar(1) = ',' -- Delimiting value to split on.
,@num as int = null -- Which value to return.
)
returns table
as
return
-- Start tally table with 10 rows.
with n(n) as (select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1)
-- Select the same number of rows as characters in @str as incremental row numbers.
-- Cross joins increase exponentially to a max possible 10,000 rows to cover largest @str length.
,t(t) as (select top (select len(isnull(@str,'')) a) row_number() over (order by (select null)) from n n1,n n2,n n3,n n4)
-- Return the position of every value that follows the specified delimiter.
,s(s) as (select 1 union all select t+1 from t where substring(isnull(@str,''),t,1) = @delimiter)
-- Return the start and length of every value, to use in the SUBSTRING function.
-- ISNULL/NULLIF combo handles the last value where there is no delimiter at the end of the string.
,l(s,l) as (select s,isnull(nullif(charindex(@delimiter,isnull(@str,''),s),0)-s,4000) from s)
select rn
,item
from(select row_number() over(order by s) as rn
,substring(@str,s,l) as item
from l
) a
where rn = @num
or @num is null;