SQL Server:将字符串拆分为行

时间:2016-12-10 11:44:00

标签: tsql split sql-server-2014

如何从下面转换数据:

CODE COMBINATION   USER
1111.111.11.0      KEN; JIMMY
666.778.0.99       KEN
888.66.77.99       LIM(JIM); JIMMY

CODE COMBINATION   USER
1111.111.11.0      KEN
1111.111.11.0      JIMMY
666.778.0.99       KEN
888.66.77.99       LIM(JIM)
888.66.77.99       JIMMY

我知道在SQL Server 2016中这可以通过分割字符串函数来完成,但我的作品是SQL Server 2014。

3 个答案:

答案 0 :(得分:4)

使用此TVF,您可以提供要拆分的字符串和分隔符。此外,您还可以获得对二次处理非常有用的序列号。

Select [CODE COMBINATION]
      ,[USER] = B.RetVal
 From  YourTable A
 Cross Apply [dbo].[udf-Str-Parse](A.[USER],';') B

返回

enter image description here

  

解析UDF

CREATE FUNCTION [dbo].[udf-Str-Parse] (@String varchar(max),@Delimiter varchar(10))
Returns Table 
As
Return (  
    Select RetSeq = Row_Number() over (Order By (Select null))
          ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
    From (Select x = Cast('<x>'+ Replace(@String,@Delimiter,'</x><x>')+'</x>' as xml).query('.')) as A 
    Cross Apply x.nodes('x') AS B(i)
);
--Select * from [dbo].[udf-Str-Parse]('Dog,Cat,House,Car',',')
--Select * from [dbo].[udf-Str-Parse]('John Cappelletti was here',' ')

现在,另一个选项是Parse-Row UDF。请注意,我们将解析后的字符串返回到一行。目前有9个职位,但很容易扩大或缩小。

Select [CODE COMBINATION]
      ,B.*
 From  YourTable A
 Cross Apply [dbo].[udf-Str-Parse-Row](A.[USER],';') B

返回

enter image description here

  

Parse Row UDF

CREATE FUNCTION [dbo].[udf-Str-Parse-Row] (@String varchar(max),@Delimiter varchar(10))
Returns Table 
As
Return (
    Select Pos1 = xDim.value('/x[1]','varchar(max)')
          ,Pos2 = xDim.value('/x[2]','varchar(max)')
          ,Pos3 = xDim.value('/x[3]','varchar(max)')
          ,Pos4 = xDim.value('/x[4]','varchar(max)')
          ,Pos5 = xDim.value('/x[5]','varchar(max)')
          ,Pos6 = xDim.value('/x[6]','varchar(max)')
          ,Pos7 = xDim.value('/x[7]','varchar(max)')
          ,Pos8 = xDim.value('/x[8]','varchar(max)')
          ,Pos9 = xDim.value('/x[9]','varchar(max)')
     From (Select Cast('<x>' + Replace(@String,@Delimiter,'</x><x>')+'</x>' as XML) as xDim) A
)
--Select * from [dbo].[udf-Str-Parse-Row]('Dog,Cat,House,Car',',')
--Select * from [dbo].[udf-Str-Parse-Row]('John Cappelletti',' ')

答案 1 :(得分:0)

您需要使用UDF在每行上拆分

CREATE FUNCTION [DBO].[FN_SPLIT_STR_TO_COL] (@T AS VARCHAR(4000) )
RETURNS
 @RESULT TABLE(VALUE VARCHAR(250))
AS
BEGIN
     SET @T= @T+';'
       ;WITH MYCTE(START,[END]) AS(

    SELECT 1 AS START,CHARINDEX(';',@T,1) AS [END]
    UNION ALL
    SELECT [END]+1 AS START,CHARINDEX(';',@T,[END]+1)AS [END] 
    FROM MYCTE WHERE [END]<LEN(@T)
    )
    INSERT INTO @RESULT 
    SELECT SUBSTRING(@T,START,[END]-START) NAME FROM MYCTE;

      RETURN 
END

现在通过使用CROSS APPLY

调用上述函数来查询您的表格
  SELECT [CodeCombination],FN_RS.VALUE FROM TABLE1
  CROSS APPLY
 (SELECT * FROM [DBO].[FN_SPLIT_STR_TO_COL] (User))           
  AS FN_RS

答案 2 :(得分:0)

如果[USER]列只有一个分号,则根本不需要“分割字符串”功能;你可以像这样使用CROSS APPLY:

-- Your Sample data 
DECLARE @table TABLE (CODE_COMBINATION varchar(30), [USER] varchar(100));
INSERT @table
VALUES ('1111.111.11.0', 'KEN; JIMMY'), ('666.778.0.99', 'XKEN'),
       ('888.66.77.99','LIM(JIM); JIMMY');

-- Solution using only CROSS APPLY
SELECT CODE_COMBINATION, [USER] = LTRIM(s.s)
FROM @table t
CROSS APPLY (VALUES (CHARINDEX(';',t.[USER]))) d(d)
CROSS APPLY 
(
  SELECT SUBSTRING(t.[USER], 1, ISNULL(NULLIF(d.d,0),1001)-1)
  UNION ALL
  SELECT SUBSTRING(t.[USER], d.d+1, 1000)
  WHERE d.d > 0
) s(s);

如果您确实需要SQL Server 2016之前的“拆分字符串”功能,我强烈建议使用Jeff Moden的DelimitedSplit8k或Eirikur Eiriksson的DelimitedSplit8K_LEAD。这两个都将胜过基于XML或递归的CTE“拆分字符串”功能。