2011-01-30 11 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番目とそれ以上の結果を見つける方法についてはまったく別です。

+2

データに不均衡なかっこはまったくないと仮定できますか? –

+0

はい。私は後でエラーを処理することができますが、実際の例が必要です。私の現実世界の問題では電子メールアドレスではありませんが、これは問題を説明し、小さな例を作成することに過ぎません。 – Daniel

答えて

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を使用して電子メールアドレスを検索し、空白または電子メールアドレス(または開始位置または先頭または最後の文字)で無効な文字に達するまで、前後にスキャンします。

+0

MSSQLにLOOPがありますか?私はちょうどSQLインターフェイスを持っています... – Daniel

+0

@ダニエル。あなたはUDFを書く必要があります。 – Tim

+0

なぜdownvote ????? T-SQLで関数を書くことができます。 – Tim

2

これは、そこには不正な括弧がありません、あなたはあなたのテキストは、任意のXMLエンティティの文字を含めることができる場合にはいくつかの追加replace Sを追加する必要がありますを前提としています。

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) 
関連する問題