-3

1 つの列が次のような電子メール ヘッダーの文字列であるクエリがあります。

From: Media Temple user (mt.kb.user@gmail.com)
Subject: article: How to Trace a Email
Date: January 25, 2011 3:30:58 PM PDT
To: user@example.com
Return-Path: <mt.kb.user@gmail.com>
Envelope-To: user@example.com
Delivery-Date: Tue, 25 Jan 2011 15:31:01 -0700
Received: from po-out-1718.google.com ([72.14.252.155]:54907) by cl35.gs01.grid ...
Received: by po-out-1718.google.com with SMTP id y22so795146pof.4 for <user@exa ...
Received: by 10.141.116.17 with SMTP id t17mr3929916rvm.251.1214951458741; Tue,...
Received: by 10.140.188.3 with HTTP; Tue, 25 Jan 2011 15:30:58 -0700 (PDT)
Dkim-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=d...
Domainkey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:da...
Message-Id: <c8f49cec0807011530k11196ad4p7cb4b9420f2ae752@mail.gmail.com>
Mime-Version: 1.0
Content-Type: multipart/alternative; boundary="----=_Part_3927_12044027.1214951...
X-Spam-Status: score=3.7 tests=DNS_FROM_RFC_POST, HTML_00_10, HTML_MESSAGE, HTM...
X-Spam-Level: ***
Message Body: This is a KnowledgeBase article that provides information on how ...

'To:'上記の例では、フィールド内に含まれる電子メール アドレスのみを抽出したいと考えていますuser@example.com

どうすればこれを達成できますか?

4

4 に答える 4

2

分割機能を使用できます。数値表を使用するバージョンが好きですが、多くの代替手段があります. まず、1,000,000 行の数値テーブル:

SET NOCOUNT ON;
DECLARE @UpperLimit INT;
SET @UpperLimit = 1000000;

WITH n(rn) AS
(
    SELECT TOP (@UpperLimit) ROW_NUMBER() OVER (ORDER BY s1.[object_id])
    FROM sys.all_columns AS s1, sys.all_objects ORDER BY s1.[object_id]
)
SELECT [Number] = rn - 1
INTO dbo.Numbers FROM n
WHERE rn <= @UpperLimit + 1;

CREATE UNIQUE CLUSTERED INDEX n ON dbo.Numbers([Number]);

区切られた文字列をセットに変換する、一般的なインラインのテーブル値分割関数になりました。

CREATE FUNCTION dbo.SplitString
(
    @List NVARCHAR(MAX),
    @Delim VARCHAR(255)
)
RETURNS TABLE
AS
    RETURN ( SELECT [Value] FROM 
      ( 
        SELECT 
          [Value] = LTRIM(RTRIM(SUBSTRING(@List, [Number],
          CHARINDEX(@Delim, @List + @Delim, [Number]) - [Number])))
        FROM dbo.Numbers WHERE Number <= LEN(@List)
        AND SUBSTRING(@Delim + @List, [Number], LEN(@Delim)) = @Delim
      ) AS x
    );
GO

それは簡単です:

DECLARE @x NVARCHAR(MAX) = N'From: Media Temple user (mt.kb.user@gmail.com)
Subject: article: How to Trace a Email
Date: January 25, 2011 3:30:58 PM PDT
To: user@example.com
Return-Path: <mt.kb.user@gmail.com>
Envelope-To: user@example.com
...';

SELECT LTRIM(SUBSTRING(Value, 4, 4000)) 
  FROM dbo.SplitString(@x, CHAR(13)+CHAR(10))
  WHERE Value LIKE 'To: %@%';

データはテーブルにありますか? わかりました、問題ありません:

DECLARE @a TABLE(id INT, email NVARCHAR(MAX));

INSERT @a VALUES
(1,N'From: Media Temple user (mt.kb.user@gmail.com)
Subject: article: How to Trace a Email
Date: January 25, 2011 3:30:58 PM PDT
To: user@example.com
Return-Path: <mt.kb.user@gmail.com>
Envelope-To: user@example.com
...'),
(2,N'From: Media Temple user (mt.kb.user@gmail.com)
Subject: article: How to Trace a Email
Date: January 25, 2011 3:30:58 PM PDT
To: differentUser@somewhereelse.com
Return-Path: <mt.kb.user@gmail.com>
Envelope-To: user@example.com
...');

SELECT a.id, LTRIM(SUBSTRING(x.Value, 4, 4000))
FROM @a AS a
CROSS APPLY dbo.SplitString(a.email, CHAR(13)+CHAR(10)) AS x
WHERE x.Value LIKE 'To: %@%';

ここで、区切り文字をいじる必要があるかもしれません-それは単にCHAR(10)、または単にCHAR(13)であるか、またはそれらが異なる順序である可能性があります-よくわからず、コードからそれが何であるかを判断できません...

于 2013-10-25T16:58:34.437 に答える
1

XML 機能を使用して行を分割し、必要なものを見つけることができます。

DECLARE @X XML

SELECT @X = CONVERT(XML, '<y><x>' + 
                REPLACE(REPLACE(value, '<', '&lt;'), CHAR(10), '</x><x>') + 
                 '</x></y>')
FROM test

SELECT [Value] = T.c.value('.','NVARCHAR(MAX)')
FROM @X.nodes('/y/x') T(c)
WHERE T.c.value('.','NVARCHAR(MAX)') LIKE 'To: %'

でテストする SQLfiddle

于 2013-10-25T17:03:22.957 に答える
0

これを試して:

select substring(@s, charindex(char(13)+char(10)+'To: ', @s) + 6, charindex(char(13), @s, charindex(char(13)+char(10)+'To: ', @s)+6) - (charindex(char(13)+char(10)+'To: ', @s)+6))

完全なテスト スクリプトは次のとおりです。

declare @s varchar(500)

set @s = 'Date: January 25, 2011 3:30:58 PM PDT
To: user@example.com
Return-Path: <mt.kb.user@gmail.com>
Envelope-To: user@example.com'

select substring(@s, charindex(char(13)+char(10)+'To: ', @s) + 6, charindex(char(13)+char(10), @s, charindex(char(13)+char(10)+'To: ', @s)+6) - (charindex(char(13)+char(10)+'To: ', @s)+6))

適切な電子メールでは、仕様RFC2822に従ってヘッダーを CRLF (char(13) + char(10)) で区切る必要があり、上記のコードは同じ仮定を行うことに注意してください。

メールの行末が異なる場合は、出現するすべての行char(13)+char(10)を単にchar(13)またはに変更する必要がある場合がありますchar(10)。その場合は、to も調整することを忘れないでください+6( +51 文字少ないため)。

于 2013-10-25T16:54:02.750 に答える
0

メールアドレスが first'To:'との間にある場合'Return-Path:'、これを使用できます ( Fiddle demo ):

declare @s nvarchar(max) = 'From: Media Temple user (mt.kb.user@gmail.com)
                        Subject: article: How to Trace a Email
                        Date: January 25, 2011 3:30:58 PM PDT
                        To: user@example.com
                        Return-Path: <mt.kb.user@gmail.com>...'

select substring(@s, charindex('To:',@s)+3, 
             charindex('Return-Path:',@s)- charindex('To:',@s)-3)

--Results
user@example.com

もう少し一般的なバージョン:メールアドレスが最初の Return-path の前にあると仮定

;with cte as (
 select reverse(left(@s, charindex('Return-Path:',@s)-1)) rs
)
select reverse(left(rs, charindex(':oT', rs)-1)) 
from cte

テーブル クエリでは、 に置き換え@s くださいcolumn name

于 2013-10-25T16:54:10.163 に答える