如何使用每列的唯一选择台词将数据插入到临时表中?

时间:2019-04-30 14:39:09

标签: sql sql-server reporting-services

我正在向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

当前输出(这是我得到的,但是错了) enter image description here

预期产量

enter image description here

第一个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

1 个答案:

答案 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;