SQL Server 按分隔符拆分

在 SQL Server 数据库中,有时我们需要将一个字符串按照特定的分隔符进行拆分,以提取出其中的各个部分。这在处理一些复杂的数据结构或者日志文件时非常实用。本文将介绍一种常用的方法来实现字符串按分隔符拆分的操作。

方法一:使用递归函数

SQL Server 提供了一个内置的字符串函数 STRING_SPLIT,它可以按照指定的分隔符将一个字符串拆分成多行。然而,这个函数只能在 SQL Server 2016 及以上的版本中使用,如果我们使用的是较低版本的 SQL Server,就需要自己实现一个类似的函数。

我们可以使用递归函数来实现字符串按分隔符拆分的操作。下面是一个示例函数的代码:

CREATE FUNCTION dbo.SplitString
(
    @inputString NVARCHAR(MAX),
    @delimiter NVARCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
    WITH cte AS
    (
        SELECT 
            1 AS id,
            CHARINDEX(@delimiter, @inputString) AS pos
        UNION ALL
        SELECT 
            id + 1,
            CHARINDEX(@delimiter, @inputString, pos + 1)
        FROM cte
        WHERE pos > 0
    )
    SELECT 
        id,
        SUBSTRING(@inputString, pos, CASE WHEN pos = 0 THEN LEN(@inputString) ELSE pos - 1 END) AS value
    FROM cte
)

上述代码定义了一个名为 SplitString 的函数,它接受两个参数:@inputString 表示待拆分的字符串,@delimiter 表示分隔符。函数使用递归的方式将字符串拆分成多个行,每行包含一个序号和一个拆分出的值。

为了演示该函数的用法,我们创建一个示例表 Employees,其中包含一列 FullNames,存储了一些员工的姓名。我们可以使用 SplitString 函数将每个姓名拆分成姓和名,并将结果存储到一个新表 SplitNames 中:

CREATE TABLE Employees
(
    Id INT PRIMARY KEY,
    FullNames NVARCHAR(MAX)
)

INSERT INTO Employees (Id, FullNames)
VALUES (1, 'John Doe, Jane Smith, Michael Johnson')

SELECT 
    e.Id,
    s.value AS FirstName,
    LTRIM(RTRIM(SUBSTRING(e.FullNames, s.pos + 1, LEN(e.FullNames) - s.pos))) AS LastName
INTO SplitNames
FROM Employees e
CROSS APPLY dbo.SplitString(e.FullNames, ',') s

在上述代码中,我们使用了 CROSS APPLY 子句来调用 SplitString 函数,并将拆分出的值存储到 SplitNames 表中。

方法二:使用 XML 解析

除了递归函数,我们还可以使用 XML 解析的方式来实现字符串按分隔符拆分的操作。这种方法的优点是相对简洁且具有较好的性能。

下面是一个示例函数的代码:

CREATE FUNCTION dbo.SplitString
(
    @inputString NVARCHAR(MAX),
    @delimiter NVARCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
    SELECT 
        ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS id,
        LTRIM(RTRIM(Item.value('.', 'NVARCHAR(MAX)'))) AS value
    FROM 
    (
        SELECT 
            CAST('<M>' + REPLACE(@inputString, @delimiter, '</M><M>') + '</M>' AS XML) AS x
    ) AS source
    CROSS APPLY x.nodes('/M') AS Split(Item)
)

上述代码定义了一个类似的名为 SplitString 的函数,它的实现方式与递归函数有所不同。函数首先将输入字符串中的每个分隔符替换为 XML 标签,然后使用 CROSS APPLY 子句将每个标签作为一行返回,最后将每行的值拆分出来。

与递归函数一样,我们可以使用该函数来拆分一个包含员工姓名的字符串:

CREATE TABLE Employees
(
    Id INT PRIMARY KEY,
    FullNames NVARCHAR(MAX)
)

INSERT INTO Employees (Id, FullNames)
VALUES (1, 'John Doe, Jane Smith, Michael Johnson')

SELECT 
    e.Id,
    s.value AS FirstName,