TSQL:将一列以分号分隔的值拆分为多行

Jen*_*nsB 2 t-sql

尝试从旧数据库迁移到存储数据方式的新数据库有点不同.

在一个特定的情况下,我有一个分号分隔值的列,我想分成多行.

这是一个例子:

SELECT 
    p.idperson, 
    p.roleperson
FROM person p
Run Code Online (Sandbox Code Playgroud)

上面的TSQL生成以下输出

idperson roleperson
1001    ;214401;
1002    ;214201;214401;
1003    ;212101;
Run Code Online (Sandbox Code Playgroud)

我想将其转换为:

idperson roleperson
1001    214401
1002    214401
1002    214201
1003    212101
Run Code Online (Sandbox Code Playgroud)

也就是说,我想将具有多个值的行拆分为两行.这可能不创建游标或循环吗?

Jen*_*nsB 7

在写这篇文章时,我想出了一个使用交叉应用和自定义分割功能的简单方法.所以,不要只问问题,我将发布我是如何使用这个自包含SQL解决它的;)

-- set up a split function
GO
CREATE FUNCTION [dbo].[TempSplit] (@sep char(1), @s varchar(512))
RETURNS table
AS
RETURN (
    WITH Pieces(pn, start, stop) AS (
      SELECT 1, 1, CHARINDEX(@sep, @s)
      UNION ALL
      SELECT pn + 1, stop + 1, CHARINDEX(@sep, @s, stop + 1)
      FROM Pieces
      WHERE stop > 0
    )
    SELECT pn,
      SUBSTRING(@s, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END) AS s
    FROM Pieces
  )
GO

-- set up some test data
DECLARE @personroles TABLE 
    (
        idperson INT,
        rawroleoptions NVARCHAR(MAX)
    )

INSERT INTO @personroles VALUES (1, ';1;2;3;')
INSERT INTO @personroles VALUES (2, ';4;5;6;')
INSERT INTO @personroles VALUES (3, ';7;')

-- the actual work --
;WITH data AS
(
    SELECT 
        p.idperson,
        p.rawroleoptions

    FROM @personroles p
)
SELECT * FROM data r
CROSS APPLY  
    (SELECT s AS [ExtractedValue] FROM dbo.TempSplit(';',r.rawroleoptions) WHERE LEN(s)>0) d

-- clean up --
GO
DROP FUNCTION dbo.TempSplit
GO
Run Code Online (Sandbox Code Playgroud)

运行以上之后,这就是SQL输出.

值拆分为新行