T SQL - 将以逗号分隔的字符串逗号转换为具有多列的表

时间:2017-11-13 02:09:18

标签: sql-server tsql

我有一个以逗号分隔的字符串(它们是记录),例如

0,CSVSO67695,97971,2014-03-05 00:00:00.000,WB-H098,1,4.99,Individual,Sales extract OK!,255.0,1,CSVSO53485,47747,2013-07-31 00:00:00.000,SJ-0194-L,10,323.94,Store,Sales extract OK!,255.0

我想解析字符串并将值放入表中。 以下是变量名称:

ID int
SalesOrderNumber  varchar(15)
SalesOrderDetailID int
OrderDate date
ProductNumber varchar(25)
Quantity int
LineTotal money
CustomerType varchar(25)
TestData_1 varchar(50)
TestData_2 varchar(50)

2 个答案:

答案 0 :(得分:0)

尝试下面的内容,看起来很大。但希望这可以帮助你:

最初使用split函数拆分字符串:

CREATE FUNCTION [dbo].[Split]
(@String VARCHAR (max), @Delimiter CHAR (1))
RETURNS 
    @temptable TABLE (
        [items] VARCHAR (max) COLLATE SQL_Latin1_General_CP1_CI_AS NULL)
AS
begin        
    declare @idx int        
    declare @slice varchar(max)        

    select @idx = 1        
        if len(@String)<1 or @String is null  return        

    while @idx!= 0        
    begin        
        set @idx = charindex(@Delimiter,@String)        
        if @idx!=0        
            set @slice = left(@String,@idx - 1)        
        else        
            set @slice = @String        

        if(len(@slice)>0)   
            insert into @temptable(Items) values(@slice)        

        set @String = right(@String,len(@String) - @idx)        
        if len(@String) = 0 break        
    end    
return        
end

然后尝试代码:

CREATE TABLE #Temp(ID int
    ,SalesOrderNumber varchar(15)
    ,SalesOrderDetailID int
    ,OrderDate date
    ,ProductNumber varchar(25)
    ,Quantity int
    ,LineTotal money
    ,CustomerType varchar(25)
    ,TestData_1 varchar(50)
    ,TestData_2 varchar(50))

DECLARE @CommaString VARCHAR(MAX)='0,CSVSO67695,97971,2014-03-05 00:00:00.000,WB-H098,1,4.99,Individual,Sales extract OK!,255.0,1,CSVSO53485,47747,2013-07-31 00:00:00.000,SJ-0194-L,10,323.94,Store,Sales extract OK!,255.0'

SELECT ROW_NUMBER() OVER(ORDER BY(SELECT NULL))RN
    ,* 
INTO #T1 
FROM dbo.Split(@CommaString,',')

INSERT INTO #Temp
SELECT D.V1,D.V2,D.V3,D.V4,D.V5,D.V6,D.V7,D.V8,D.V9,D.V10
FROM(
    SELECT (RN-1)/10 V
        ,MAX(CASE WHEN RN%10=1 THEN items END)V1,MAX(CASE WHEN RN%10=2 THEN items END)V2,MAX(CASE WHEN RN%10=3 THEN items END)V3,MAX(CASE WHEN RN%10=4 THEN items END)V4
        ,MAX(CASE WHEN RN%10=5 THEN items END)V5,MAX(CASE WHEN RN%10=6 THEN items END)V6,MAX(CASE WHEN RN%10=7 THEN items END)V7,MAX(CASE WHEN RN%10=8 THEN items END)V8
        ,MAX(CASE WHEN RN%10=9 THEN items END)V9,MAX(CASE WHEN RN%10=0 THEN items END)V10
    FROM #T1
    GROUP BY (RN-1)/10
    )D

SELECT * FROM #Temp

DROP TABLE #Temp
DROP TABLE #T1

答案 1 :(得分:0)

如果性能很重要且您只需要字符串中的前10个元素,则可以使用cascading cross apply,如下所示:

declare @CommaString varchar(MAX)='0,CSVSO67695,97971,2014-03-05 00:00:00.000,WB-H098,1,4.99,Individual,Sales extract OK!,255.0,1,CSVSO53485,47747,2013-07-31 00:00:00.000,SJ-0194-L,10,323.94,Store,Sales extract OK!,255.00000';

select --d1=d1.d,d2=d2.d,d3=d3.d, d4=d4.d, d5=d5.d,d6=d6.d,d7=d7.d,d8=d8.d,d9=d9.d,d10=d10.d, d11=d11.d,
  ID                 = substring(v.cs, 1, d1.d-1),
  SalesOrderNumber   = substring(v.cs, d1.d+1, d2.d-1-d1.d),
  SalesOrderDetailID = substring(v.cs, d2.d+1, d3.d-1-d2.d),
  OrderDate          = substring(v.cs, d3.d+1, d4.d-1-d3.d),
  ProductNumber      = substring(v.cs, d4.d+1, d5.d-1-d4.d),
  Quantity           = substring(v.cs, d5.d+1, d6.d-1-d5.d),
  LineTotal          = substring(v.cs, d6.d+1, d7.d-1-d6.d),
  CustomerType       = substring(v.cs, d7.d+1, d8.d-1-d7.d),
  TestData_1         = substring(v.cs, d8.d+1, d9.d-1-d8.d),
  TestData_2         = substring(v.cs, d9.d+1, d10.d-1-d9.d)
from (values (@CommaString)) v(cs)
cross apply (values (len(@commastring)-len(replace(@commastring,',',''))+1)) c(commacount)
cross apply (values (charindex(',', v.cs)))          d1(d)
cross apply (values (charindex(',', v.cs, d1.d+1)))  d2(d)
cross apply (values (charindex(',', v.cs, d2.d+1)))  d3(d)
cross apply (values (charindex(',', v.cs, d3.d+1)))  d4(d)
cross apply (values (charindex(',', v.cs, d4.d+1)))  d5(d)
cross apply (values (charindex(',', v.cs, d5.d+1)))  d6(d)
cross apply (values (charindex(',', v.cs, d6.d+1)))  d7(d)
cross apply (values (charindex(',', v.cs, d7.d+1)))  d8(d)
cross apply (values (charindex(',', v.cs, d8.d+1)))  d9(d)
cross apply (values (charindex(',', v.cs, d9.d+1)))  d10(d)
cross apply (values (charindex(',', v.cs, d10.d+1))) d11(d)
where c.commaCount >= 10 -- optional where clause to ensure that there are enough commas
option (recompile);

返回:

ID  SalesOrderNumber  SalesOrderDetailID  OrderDate                ProductNumber  Quantity   LineTotal  CustomerType  TestData_1         TestData_2
--- ----------------- ------------------- ------------------------ -------------- ---------- ---------- ------------- ------------------ ----------
0   CSVSO67695        97971               2014-03-05 00:00:00.000  WB-H098        1          4.99       Individual    Sales extract OK!  255.0

这种技术与分割字符串一样高效。请注意下面的执行计划。一次恒定扫描,总成本为0.0000012的SELECT大约和它一样高效。特别是对于varchar(max)和其他blob数据类型。

enter image description here