在SQL Server中拆分包含2个分隔符的字符串

时间:2015-01-14 18:05:11

标签: sql sql-server sql-server-2008

我的SQL Server数据库中有一些错误的数据。

看起来像这样:

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

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

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

分割后,结果将添加到同一个表中的3列:

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

2 个答案:

答案 0 :(得分:1)

 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)
  • 查看有效的FIDDLE here

<强>更新

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

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

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

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

答案 1 :(得分:0)

第一步我会清理你的数据。 SQL Server具有您可以使用的Replace功能。

REPLACE ( string_expression , string_pattern , string_replacement )

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

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

首先会替换逗号,然后是分号。导致ab|de|ghi|de

或者,您可以通过在生成的拆分上运行游标(使用您用于拆分的任何机制)来多次拆分数据。