将分号分隔符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