将字符串拆分为sql server中的行

时间:2014-12-23 15:08:15

标签: sql-server sql-server-2008

我在sql ABCDEF中有一个字符串。这是First_Name表中的EMP列。 我想将此字符串拆分为行,如下所示。

请注意,没有分隔符或逗号或空格。它是一个没有任何特殊字符和特殊符号和空格的字符串。

First_Name
A
B
C
D
E
F

3 个答案:

答案 0 :(得分:4)

如果你有Numbers表,解决这个问题是微不足道的。不需要循环或游标,因此性能比其他解决方案好几个数量级:

declare @name varchar(10)='ABCDEF'

select @name,SUBSTRING(@name,n,1)
from numbers
where n<=LEN(@name)

或者

select EMP.First_Name,SUBSTRING(EMP.First_Name,n,1)
from EMP,numbers
where n<=LEN(EMP.First_Name)

Numbers表仅包含从1到足够大的数字。您可以使用以下语句创建这样的表(从链接的文章中借用):

SELECT TOP (1000000) n = CONVERT(INT, ROW_NUMBER() OVER (ORDER BY s1.[object_id]))
INTO dbo.Numbers
FROM sys.all_objects AS s1 CROSS JOIN sys.all_objects AS s2
OPTION (MAXDOP 1);

CREATE UNIQUE CLUSTERED INDEX n ON dbo.Numbers(n)

答案 1 :(得分:3)

显然会出现一个循环,但我们可以做得更好。这是一个理货或数字表完美的地方。我在我的系统中有一个这样的视图,可以根据需要创建一个包含10,000行的表。有很多方法可以创建这样的表,或者你可以创建一个持久的表来获得轻微的性能提升。

create View [dbo].[cteTally] as

WITH
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
    cteTally(N) AS 
    (
        SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
    )
select N from cteTally

现在我们已经认识到这种类型的东西使用完全基于集合的方法并放弃循环的概念是超级无痛的。

declare @Something varchar(20) = 'ABCDEF'

select SUBSTRING(@Something, N, 1)
from cteTally t
where t.N < LEN(@Something)

答案 2 :(得分:0)

您可以使用CTE将字符串的每个字符解析为新行:

DECLARE @data varchar(200) = 'ABCDEF'

;WITH CTE AS (
    SELECT
        1 as CharacterPosition,
        SUBSTRING(@data,1,1) as Character
    UNION ALL
    SELECT
        CharacterPosition + 1,
        SUBSTRING(@data,CharacterPosition + 1,1)
    FROM
        CTE
    WHERE CharacterPosition < LEN(@data)
)
SELECT Character
FROM CTE