2011-01-30 23 views
3

我有下表數據:如何從SQL Server中的單行中提取多個字符串

id | text 
-------------------------------------------------------------------------------- 
1  | Peter ([email protected]) and Marta ([email protected]) are doing fine. 
2  | Nothing special here 
3  | Another email address ([email protected]) 

現在我需要一個選擇返回的所有電子郵件地址從我的文本列(它的好,只是檢查括號),如果有多個,返回多行地址在文本列中。我知道how to extract the first element,但我完全不知道如何找到第二個和更多的結果。

+2

我們可以假設數據中絕對沒有不平衡的括號嗎? – 2011-01-30 13:29:38

+0

是的。我可以在以後處理這些錯誤,但需要一個可行的例子來繼續。在我現實世界的問題中,根本不是電子郵件地址,這只是爲了說明問題並創建一個小例子。 – Daniel 2011-01-30 13:32:28

回答

5

您可以遞歸地使用cte去除字符串。

declare @T table (id int, [text] nvarchar(max)) 

insert into @T values (1, 'Peter ([email protected]) and Marta ([email protected]) are doing fine.') 
insert into @T values (2, 'Nothing special here') 
insert into @T values (3, 'Another email address ([email protected])') 

;with cte([text], email) 
as 
(
    select 
     right([text], len([text]) - charindex(')', [text], 0)), 
     substring([text], charindex('(', [text], 0) + 1, charindex(')', [text], 0) - charindex('(', [text], 0) - 1) 
    from @T 
    where charindex('(', [text], 0) > 0 
    union all 
    select 
     right([text], len([text]) - charindex(')', [text], 0)), 
     substring([text], charindex('(', [text], 0) + 1, charindex(')', [text], 0) - charindex('(', [text], 0) - 1) 
    from cte 
    where charindex('(', [text], 0) > 0 
) 
select email 
from cte 

結果

email 
[email protected] 
[email protected] 
[email protected] 
-1

子串函數有起始位置參數。因此,您可以找到第一個匹配項,然後在出現位置+ occurenceLength處開始下一個搜索(在您的循環中)。您需要編寫一個函數,以返回值作爲分隔字符串或表。使用@ -sign找到您的電子郵件地址,然後向後和向前掃描,直到您到達空白區域或電子郵件地址中無效的字符(或start-pos或開始或最後一個字符)。

2

這是假設沒有流氓括號,你需要在如果你的文本可以包含任何XML實體字符添加一些額外的replace秒。

WITH basedata(id, [text]) 
    AS (SELECT 1, 'Peter ([email protected]) and Marta ([email protected]) are doing fine.' 
     UNION ALL 
     SELECT 2, 'Nothing special here' 
     UNION ALL 
     SELECT 3, 'Another email address ([email protected])'), 
    cte(id, t, x) 
    AS (SELECT *, 
       CAST('<foo>' + REPLACE(REPLACE([text],'(','<bar>'),')','</bar>') + '</foo>' AS XML) 
     FROM basedata) 
SELECT id, 
     a.value('.', 'nvarchar(max)') as address 
FROM cte 
     CROSS APPLY x.nodes('//foo/bar') as addresses(a) 
相關問題