在 SQL 服务器中用 2 个分隔符拆分字符串

Split a string with 2 delimiters in SQL Server

我的 SQL 服务器数据库中有一些错误数据。

看起来像这样:

abc.qwerty@yahoo.com|fubar@cc.uk|helloworld@gmail.com

abc.qwerty@yahoo.com;fubar@cc.uk

如果分隔符可以是“|”、“;”、“,”中的任何一个,我如何将它们拆分为单独的电子邮件。

拆分后,结果将添加到同一列中的3列table:

Email1: abc.qwerty@yahoo.com, Email2: fubar@cc.uk, Email3: helloworld@gmail.com

第一步我会清理你的数据。 SQL服务器有一个Replace功能你可以使用。

REPLACE ( string_expression , string_pattern , string_replacement )

您可以在 SQL Server Management Studio 中 运行 的示例:

select Replace(Replace('ab|de,ghi;de', ',', '|'), ';', '|')

会先替换逗号,再替换分号。结果 ab|de|ghi|de

或者,您可以通过 运行在结果拆分上放置一个游标来多次拆分数据(使用您用于拆分的任何机制。

 DECLARE @STR NVARCHAR(MAX)='abc.es@yahoo.com|shudo@cc.uk|maria@gmail.com,      abc.es@yahoo.com;shudo@cc.uk'

-- Converts values to rows
SELECT Split.a.value('.', 'VARCHAR(100)') 'Ids' 
FROM  
(
     -- Use 3 REPLACE for  '|', ';', ','
     SELECT CAST ('<M>' + REPLACE(REPLACE(REPLACE(@STR, '|', '</M><M>'),',','</M><M>'),';','</M><M>') + '</M>' AS XML) AS Data      

) AS A 
CROSS APPLY Data.nodes ('/M') AS Split(a)
  • 查看工作FIDDLEhere

更新

如果您希望逗号分隔值作为最终字符串,您可以执行以下操作

DECLARE @STR NVARCHAR(MAX)='abc.qwerty@yahoo.com|fubar@cc.uk|helloworld@gmail.com,abc.qwerty@yahoo.com;fubar@cc.uk '
DECLARE @Final VARCHAR(MAX)='';


-- Converts values to rows
;WITH CTE AS
(
    SELECT DISTINCT 
    Split.a.value('.', 'VARCHAR(100)') 'Ids' 
    FROM  
    (
         -- Use 3 REPLACE for  '|', ';', ','
         SELECT CAST ('<M>' + REPLACE(REPLACE(REPLACE(@STR, '|', '</M><M>'),',','</M><M>'),';','</M><M>') + '</M>' AS XML) AS Data      

    ) AS A 
    CROSS APPLY Data.nodes ('/M') AS Split(a)
)
-- Convert to Comma Seperated Values
SELECT @Final += 
Isnull('Email' + CAST(ROW_NUMBER() OVER(ORDER BY IDS)AS VARCHAR(10))  + ': ' + Ids, '') + ', ' 
FROM CTE

SELECT LEFT(@Final,len(@Final)-1)

PRINT @Final

更新 2:将分隔符分隔的值拆分为行并动态转换为列

我在查询里面写了逻辑

DECLARE @STR NVARCHAR(MAX)='abc.es@yahoo.com|shudo@cc.uk|maria@gmail.com,abc.es@yahoo.com;shudo@cc.uk'

;WITH CTE AS
(
        -- Converts values to rows
    SELECT DISTINCT Split.a.value('.', 'VARCHAR(100)') 'Ids'
    FROM  
    (
         -- Use 3 REPLACE for  '|', ';', ','
         SELECT CAST ('<M>' + REPLACE(REPLACE(REPLACE(@STR, '|', '</M><M>'),',','</M><M>'),';','</M><M>') + '</M>' AS XML) AS Data      

    ) AS A 
    CROSS APPLY Data.nodes ('/M') AS Split(a)
)
-- Create a column to order Emails like Email1,Email2.... and insert to a temp table
-- It can be done without temp table, but its for sake of readability
SELECT 'Email' + CAST(ROW_NUMBER() OVER(ORDER BY Ids)AS VARCHAR(10)) EMails,Ids
INTO #TEMP
FROM CTE

-- Get columns to pivot
DECLARE @cols NVARCHAR (MAX)
SELECT @cols = COALESCE (@cols + ',[' + EMails + ']','[' + EMails + ']')
               FROM    (SELECT DISTINCT EMails FROM #TEMP) PV  
               ORDER BY EMails

-- Pivot the result(convert to columns from rows)
DECLARE @query NVARCHAR(MAX)
SET @query = 'SELECT * FROM 
             (
                 SELECT EMails,Ids 
                 FROM #TEMP
             ) x
             PIVOT 
             (
                 MIN(Ids)
                 FOR EMails IN (' + @cols + ')
            ) p;' 

EXEC SP_EXECUTESQL @query

现在,如果您想将电子邮件插入到您创建的 table 中,您可以使用以下代码

DECLARE @query NVARCHAR(MAX)
SET @query = 'INSERT INTO YOURTABLE(' + @cols + ')
             SELECT * FROM 
             (
                 SELECT EMails,Ids 
                 FROM #TEMP
             ) x
             PIVOT 
             (
                 MIN(Ids)
                 FOR EMails IN (' + @cols + ')
            ) p;' 

EXEC SP_EXECUTESQL @query