SQL 2005 在分隔符上拆分逗号分隔列
Posted
技术标签:
【中文标题】SQL 2005 在分隔符上拆分逗号分隔列【英文标题】:SQL 2005 Split Comma Separated Column on Delimiter 【发布时间】:2009-06-04 15:48:05 【问题描述】:我的谷歌搜索如何在分隔符上分割字符串,结果发现了一些有用的函数,用于在字符串已知时分割字符串(即见下文):
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[Split] (@String varchar(8000), @Delimiter char(1))
returns @temptable TABLE (items 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(Items) values(@slice)
set @String = right(@String,len(@String) - @idx)
if len(@String) = 0 break
end
return
end
这适用于已知字符串,例如:
SELECT TOP 10 * FROM dbo.Split('This,Is,My,List',',')
但是,我想将一列传递给一个函数,并将它与我自己行中的其他数据联合在一起......例如给定数据:
CommaColumn ValueColumn1 ValueColumn2
----------- ------------ -------------
ABC,123 1 2
XYZ, 789 2 3
我想写这样的东西:
SELECT Split(CommaColumn,',') As SplitValue, ValueColumn1, ValueColumn2 FROM MyTable
然后回来
SplitValue ValueColumn1 ValueColumn2
---------- ------------ ------------
ABC 1 2
123 1 2
XYZ 2 3
789 2 3
这可能吗,或者以前有人这样做过吗?
【问题讨论】:
99% 的时间或更多的逗号分隔列首先是由于糟糕的数据库设计造成的。服务器级别拆分函数的唯一位置是将这些列重构到自己的表中。 我希望这张表来自您的暂存数据库,并且包含来自您无法更改表布局的专有系统的原始数据? 【参考方案1】:是的,可以使用 CROSS APPLY (SQL 2005+):
with testdata (CommaColumn, ValueColumn1, ValueColumn2) as (
select 'ABC,123', 1, 2 union all
select 'XYZ, 789', 2, 3
)
select
b.items as SplitValue
, a.ValueColumn1
, a.ValueColumn2
from testdata a
cross apply dbo.Split(a.CommaColumn,',') b
注意事项:
您应该为拆分列的结果集添加一个索引,以便它返回两列,IndexNumber 和 Value。
使用数字表的内联实现通常比此处的程序版本更快。
例如:
create function [dbo].[Split] (@list nvarchar(max), @delimiter nchar(1) = N',')
returns table
as
return (
select
Number = row_number() over (order by Number)
, [Value] = ltrim(rtrim(convert(nvarchar(4000),
substring(@list, Number
, charindex(@delimiter, @list+@delimiter, Number)-Number
)
)))
from dbo.Numbers
where Number <= convert(int, len(@list))
and substring(@delimiter + @list, Number, 1) = @delimiter
)
Erland Sommarskog 对此有权威的页面,我认为:http://www.sommarskog.se/arrays-in-sql-2005.html
【讨论】:
优秀的彼得。让我的 a** 摆脱了很多麻烦:)【参考方案2】:以正确的方式修复它 - 使该列成为相关表。用逗号分隔的标量列没有任何好处。
【讨论】:
很遗憾不是我的理想情况,但仍然是正确的。【参考方案3】:+1 反对 CSV cmets,但如果您必须这样做,您将使用 CROSS APPLY 或 OUTER APPLY。
【讨论】:
【参考方案4】:alter procedure [dbo].[usp_split](@strings varchar(max)) as
begin
Declare @index int
set @index=1
declare @length int
set @length=len(@strings)
declare @str varchar(max)
declare @diff int
declare @Tags table(id varchar(30))
while(@index<@length)
begin
if(@index='1')
begin
set @str=(SELECT substring(@strings, @index, (charindex(',',(substring(@strings, @index,(@length)))))-1))
insert into @Tags values(@str)
set @index=(charindex(',',(substring(@strings, @index,(@length)))))
end
else
begin
set @diff=@length-@index
if(@diff !=0)
begin
set @str=(select substring(@strings, @index, (charindex(',',(substring(@strings,@index,@diff))))-1))
if(@str is not null and @str!='')
begin
insert into @Tags VALUES(@str)
end
set @index=@index +(charindex(',',(substring(@strings, @index,@diff))))
end
end
end
set @str=(select right(@strings,(charindex(',',(substring(reverse(@strings),1,(@length)))))-1))
insert into @Tags VALUES(@str)
select id from @Tags
end
用法:
exec usp_split '1212,21213,1,3,133,1313131,1,231313,5'
【讨论】:
【参考方案5】:你可以试试这样的:
SELECT s.Items AS SplitValue, ValueColumn1, ValueColumn2
FROM MyTable, Split(CommaColumn,',') AS s
【讨论】:
试过了,不幸的是没有用。谢谢你的尝试。以上是关于SQL 2005 在分隔符上拆分逗号分隔列的主要内容,如果未能解决你的问题,请参考以下文章