我想将数据库字段中的分隔字符串解析为多个列。该字符串可以包含由特殊字符(在我的特定情况下为char(7))分隔的0到7个组件。不会超过七个组成部分;如果有,它们将被忽略并包含在最后一个组件中的分隔符中。 我需要在不使用UDF或T-SQL的情况下执行此操作。我不认为XML解析功能非常适合这种情况,但我认为这是一种有效的解决方案。
留下字符串操作函数。 由于我在SQL Server 2008 R2中,所以string_split()函数不是一个选项。强力方法(下面)似乎有效,但它不实用且难以理解。我对它的任何改进都感兴趣。
create table #x (a int, delimited_value varchar(8000))
insert into #x values
(1, 'abc')
,(2, 'defgh' + char(7) + 'ij' + char(7) + 'klmnop')
,(3, '')
,(4, 'qr' + char(7) + 's' + char(7) + 't' + char(7) + 'u' + char(7) + 'v' + char(7) + 'w' + char(7) + 'xyz')
,(5, '012' + char(7) + char(7) + '3' + char(7))
,(6, char(7) + char(7) + '4567' + char(7) + char(7) + '89')
select a
,substring(delimited_value, 1, isnull(nullif(charindex(char(7), delimited_value), 0), 8000) - 1) as component1
,substring(delimited_value, isnull(nullif(charindex(char(7), delimited_value), 0) + 1, 8000), isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value), 0), 8000) + 1 ), 0), 8001) - isnull(nullif(charindex(char(7), delimited_value), 0), 8000) - 1) as component2
,substring(delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value), 0), 8000) + 1 ), 0) + 1, 8000), isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value), 0), 8000) + 1 ), 0), 8000) + 1 ), 0), 8001) - isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value), 0), 8000) + 1 ), 0), 8000) - 1) as component3
,substring(delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value), 0), 8000) + 1 ), 0), 8000) + 1 ), 0) + 1, 8000), isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value), 0), 8000) + 1 ), 0), 8000) + 1 ), 0), 8000) + 1 ), 0), 8001) - isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value), 0), 8000) + 1 ), 0), 8000) + 1 ), 0), 8000) - 1) as component4
,substring(delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value), 0), 8000) + 1 ), 0), 8000) + 1 ), 0), 8000) + 1 ), 0) + 1, 8000), isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value), 0), 8000) + 1 ), 0), 8000) + 1 ), 0), 8000) + 1 ), 0), 8001) + 1 ), 0), 8001) - isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value), 0), 8000) + 1 ), 0), 8000) + 1 ), 0), 8000) + 1 ), 0), 8000) - 1) as component5
,substring(delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value), 0), 8000) + 1 ), 0), 8000) + 1 ), 0), 8000) + 1 ), 0), 8000) + 1 ), 0) + 1, 8000), isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value), 0), 8000) + 1 ), 0), 8000) + 1 ), 0), 8000) + 1 ), 0), 8000) + 1 ), 0), 8000) + 1 ), 0), 8001) - isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value), 0), 8000) + 1 ), 0), 8000) + 1 ), 0), 8000) + 1 ), 0), 8000) + 1 ), 0), 8000) - 1) as component6
,substring(delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value, isnull(nullif(charindex(char(7), delimited_value), 0), 8000) + 1 ), 0), 8000) + 1 ), 0), 8000) + 1 ), 0), 8000) + 1 ), 0), 8000) + 1 ), 0) + 1, 8000), 8000) as component7
from #x
答案 0 :(得分:2)
尽管要求不使用功能,但我发布了一个使用一个功能的解决方案。这是一个内联表值函数,并且速度非常快。如果没有使用CLR,你就不会在那里找到快速分离器。你可以在这里找到文章和代码。 http://www.sqlservercentral.com/articles/Tally+Table/72993/
如果你不喜欢那个,那么这里还有其他几个很好的选择。 https://sqlperformance.com/2012/07/t-sql-queries/split-strings
使用Jeff Moden分割器(来自上面的第一个链接),您的代码就是这么简单。
select x.a
, component1 = max(case when y.ItemNumber = 1 then y.Item end)
, component2 = max(case when y.ItemNumber = 2 then y.Item end)
, component3 = max(case when y.ItemNumber = 3 then y.Item end)
, component4 = max(case when y.ItemNumber = 4 then y.Item end)
, component5 = max(case when y.ItemNumber = 5 then y.Item end)
, component6 = max(case when y.ItemNumber = 6 then y.Item end)
, component7 = max(case when y.ItemNumber = 7 then y.Item end)
from #x x
cross apply dbo.DelimitedSplit8K(x.delimited_value, char(7)) y
group by x.a
答案 1 :(得分:2)
我认为XML方法在这里是简单而有效的解决方案。
示例强>
Select A.a
,B.*
From #x A
Cross Apply (
Select Pos1 = ltrim(rtrim(xDim.value('/x[1]','varchar(max)')))
,Pos2 = ltrim(rtrim(xDim.value('/x[2]','varchar(max)')))
,Pos3 = ltrim(rtrim(xDim.value('/x[3]','varchar(max)')))
,Pos4 = ltrim(rtrim(xDim.value('/x[4]','varchar(max)')))
,Pos5 = ltrim(rtrim(xDim.value('/x[5]','varchar(max)')))
,Pos6 = ltrim(rtrim(xDim.value('/x[6]','varchar(max)')))
,Pos7 = ltrim(rtrim(xDim.value('/x[7]','varchar(max)')))
From (Select Cast('<x>' + replace(delimited_value,char(7),'</x><x>')+'</x>' as xml) as xDim) as A
) B
返回
a Pos1 Pos2 Pos3 Pos4 Pos5 Pos6 Pos7
1 abc NULL NULL NULL NULL NULL NULL
2 defgh ij klmnop NULL NULL NULL NULL
3 NULL NULL NULL NULL NULL NULL
4 qr s t u v w xyz
5 012 3 NULL NULL NULL
6 4567 89 NULL NULL