将分号分隔符SQL拆分为行

将分号分隔符SQL拆分为行,sql,sql-server,csv,split,Sql,Sql Server,Csv,Split,我只是想寻求帮助。 我试图用分号作为分隔符拆分分隔值。 无法将逗号替换为分号,因为存在具有逗号的值 ID Value 1 | A&B;C;D;E, F 转换为: ID Value 1 A&B 1 C 1 D 1 E, F 我试着调整我在网上得到的SQL脚本,但没有成功 SELECT F1.ID, O.splitdata FROM ( SELECT OldID, cast('<X>'+replace((SELECT Co

我只是想寻求帮助。 我试图用分号作为分隔符拆分分隔值。 无法将逗号替换为分号,因为存在具有逗号的值

ID   Value
1   | A&B;C;D;E, F
转换为:

ID   Value
1    A&B
1    C
1    D
1    E, F
我试着调整我在网上得到的SQL脚本,但没有成功

SELECT F1.ID,
 O.splitdata 
FROM
 (
 SELECT OldID,
 cast('<X>'+replace((SELECT ColumnName + '' FOR XML PATH('')),';','</X><X>')+'</X>' as XML) as xmlfilter from TableName F
 )F1
 CROSS APPLY
 ( 
 SELECT fdata.D.value('.','varchar(max)') as splitdata 
 FROM f1.xmlfilter.nodes('X') as fdata(D)) O

谢谢

请使用下面的函数按特定分隔符拆分字符串:

CREATE FUNCTION [dbo].[Split](@String varchar(8000), @Delimiter char(1))        
returns @temptable TABLE (SplitValue varchar(8000))        
as        
begin        
    declare @idx int        
    declare @slice varchar(8000)        

    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(SplitValue) values(@slice)        

        set @String = right(@String,len(@String) - @idx)        
        if len(@String) = 0 break        
    end    
return       
end
Declare @Dummy table (ID int, SomeTextToSplit varchar(max))
Insert Into @Dummy values
 (1,'A&B;C;D;E, F')
,(2,'"C" & "D";<C>;D;E, F');

DECLARE @Delimiter VARCHAR(10)=';';
WITH Casted AS
(
    SELECT *
          ,CAST('<x>' + REPLACE((SELECT REPLACE(SomeTextToSplit,@Delimiter,'§§Split$me$here§§') AS [*] FOR XML PATH('')),'§§Split$me$here§§','</x><x>') + '</x>' AS XML) AS SplitMe
    FROM @Dummy
)
SELECT Casted.*
      ,x.value('.','nvarchar(max)') AS Part 
FROM Casted
CROSS APPLY SplitMe.nodes('/x') AS A(x)
如果您有任何疑问,请告诉我

谢谢。

带有自定义项的选项1

没有自定义项的选项2

这个UDF是XML安全的,而且速度非常快


如果您不喜欢某个函数,或者您没有创建新函数的权限,那么可以使用非常快速的XML方法。在您的例子中,由于特殊字符和;作为分隔符:

CREATE FUNCTION [dbo].[Split](@String varchar(8000), @Delimiter char(1))        
returns @temptable TABLE (SplitValue varchar(8000))        
as        
begin        
    declare @idx int        
    declare @slice varchar(8000)        

    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(SplitValue) values(@slice)        

        set @String = right(@String,len(@String) - @idx)        
        if len(@String) = 0 break        
    end    
return       
end
Declare @Dummy table (ID int, SomeTextToSplit varchar(max))
Insert Into @Dummy values
 (1,'A&B;C;D;E, F')
,(2,'"C" & "D";<C>;D;E, F');

DECLARE @Delimiter VARCHAR(10)=';';
WITH Casted AS
(
    SELECT *
          ,CAST('<x>' + REPLACE((SELECT REPLACE(SomeTextToSplit,@Delimiter,'§§Split$me$here§§') AS [*] FOR XML PATH('')),'§§Split$me$here§§','</x><x>') + '</x>' AS XML) AS SplitMe
    FROM @Dummy
)
SELECT Casted.*
      ,x.value('.','nvarchar(max)') AS Part 
FROM Casted
CROSS APPLY SplitMe.nodes('/x') AS A(x)
结果

1   A&B
1   C
1   D
1   E, F
2   "C" & "D"
2   <C>
2   D
2   E, F

有很多字符串拆分技术,您不必使用基于XML的函数。阅读Aaron bertrand的并选择一个不同的函数。快速搜索类似于分隔符上sql拆分字符串的内容会提供大量选项,包括上面链接的优秀文章-你有没有尝试过任何易于搜索的替代方法?如果你删除&你的查询会很好@mirelle@mohan111我刚刚发布了一个答案,允许在XML-string-spliting中使用这些字符。Serg链接的可能重复项是一个可能的方法的伟大列表,但非常古老。很多答案都过时了。。。我将在提示下以复制的形式关闭它,以查找更新的答案…带有循环的方法已经过时了…非常好-迁移到我的XML解析函数中谢谢!它确实起作用了。只需注意,空值变为空白。但尽管如此,它工作得很好。它运行了28秒,而我的光标脚本运行了10分钟。@MirelleGameng,不太正确。。。如果字符串包含两个分号,一个接一个SomeValue;;更重要的是,这两者之间没有任何区别。这不是作为空白=空格读取,而是作为空字符串=*零长度字符串*。如果需要,可以使用NULLIF将其转换为NULL。如果这有效,请接受答案,谢谢!已经接受了。再次感谢@Shnugo:
CREATE FUNCTION [dbo].[udf-Str-Parse-8K] (@String varchar(max),@Delimiter varchar(25))
Returns Table 
As
Return (  
    with   cte1(N)   As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)),
           cte2(N)   As (Select Top (IsNull(DataLength(@String),0)) Row_Number() over (Order By (Select NULL)) From (Select N=1 From cte1 a,cte1 b,cte1 c,cte1 d) A ),
           cte3(N)   As (Select 1 Union All Select t.N+DataLength(@Delimiter) From cte2 t Where Substring(@String,t.N,DataLength(@Delimiter)) = @Delimiter),
           cte4(N,L) As (Select S.N,IsNull(NullIf(CharIndex(@Delimiter,@String,s.N),0)-S.N,8000) From cte3 S)

    Select RetSeq = Row_Number() over (Order By A.N)
          ,RetVal = LTrim(RTrim(Substring(@String, A.N, A.L)))
    From   cte4 A
);
--Orginal Source http://www.sqlservercentral.com/articles/Tally+Table/72993/
--Much faster than str-Parse, but limited to 8K
--Select * from [dbo].[udf-Str-Parse-8K]('Dog,Cat,House,Car',',')
--Select * from [dbo].[udf-Str-Parse-8K]('John||Cappelletti||was||here','||')
Declare @Dummy table (ID int, SomeTextToSplit varchar(max))
Insert Into @Dummy values
 (1,'A&B;C;D;E, F')
,(2,'"C" & "D";<C>;D;E, F');

DECLARE @Delimiter VARCHAR(10)=';';
WITH Casted AS
(
    SELECT *
          ,CAST('<x>' + REPLACE((SELECT REPLACE(SomeTextToSplit,@Delimiter,'§§Split$me$here§§') AS [*] FOR XML PATH('')),'§§Split$me$here§§','</x><x>') + '</x>' AS XML) AS SplitMe
    FROM @Dummy
)
SELECT Casted.*
      ,x.value('.','nvarchar(max)') AS Part 
FROM Casted
CROSS APPLY SplitMe.nodes('/x') AS A(x)
1   A&B
1   C
1   D
1   E, F
2   "C" & "D"
2   <C>
2   D
2   E, F