27

Exchange 2007 から SQL にメッセージ追跡ログを挿入する作業を行っている背景情報を提供するために、ここでアドバイスをお願いします。1 日に何百万もの行があるため、Bulk Insert ステートメントを使用してデータを SQL テーブルに挿入しています。

実際、私は実際に一時テーブルに一括挿入し、そこからデータをライブテーブルにマージします。これは、特定のフィールドが値の周りに引用符などを持っているため、解析の問題をテストするためです。

これは、受信者アドレス列が ; で区切られた区切りフィールドであるという事実を除いて、うまく機能します。多くの電子メール受信者がいる可能性があるため、非常に長くなる場合があります。

この列を取得して、値を複数の行に分割し、それを別のテーブルに挿入したいと思います。問題は、私がしようとしていることが、時間がかかりすぎているか、思い通りに機能していないことです。

この例のデータを取ります:

message-id                                              recipient-address
2D5E558D4B5A3D4F962DA5051EE364BE06CF37A3A5@Server.com   user1@domain1.com
E52F650C53A275488552FFD49F98E9A6BEA1262E@Server.com     user2@domain2.com
4fd70c47.4d600e0a.0a7b.ffff87e1@Server.com              user3@domain3.com;user4@domain4.com;user5@domain5.com

これを受信者テーブルで次のようにフォーマットしたいと思います。

message-id                                              recipient-address
2D5E558D4B5A3D4F962DA5051EE364BE06CF37A3A5@Server.com   user1@domain1.com
E52F650C53A275488552FFD49F98E9A6BEA1262E@Server.com     user2@domain2.com
4fd70c47.4d600e0a.0a7b.ffff87e1@Server.com              user3@domain3.com
4fd70c47.4d600e0a.0a7b.ffff87e1@Server.com              user4@domain4.com
4fd70c47.4d600e0a.0a7b.ffff87e1@Server.com              user5@domain5.com

どうすればこれを行うことができるかについて誰かアイデアがありますか?

私は PowerShell をよく知っているので、それを試してみましたが、28K レコードの foreach ループでさえ、処理に永遠に時間がかかりました。可能な限り迅速/効率的に実行されるものが必要です。

ありがとう!

4

4 に答える 4

62

SQL Server 2016 以降を使用している場合

新しいSTRING_SPLIT関数を使用できます。これについては、私がここでブログを書いており、Brent Ozar がここでブログを書いています

SELECT s.[message-id], f.value
  FROM dbo.SourceData AS s
  CROSS APPLY STRING_SPLIT(s.[recipient-address], ';') as f;

まだ SQL Server 2016 より前のバージョンを使用している場合

分割関数を作成します。これは多くの例の 1 つにすぎません。

CREATE FUNCTION dbo.SplitStrings
(
    @List       NVARCHAR(MAX),
    @Delimiter  NVARCHAR(255)
)
RETURNS TABLE
AS
    RETURN (SELECT Number = ROW_NUMBER() OVER (ORDER BY Number),
        Item FROM (SELECT Number, Item = LTRIM(RTRIM(SUBSTRING(@List, Number, 
        CHARINDEX(@Delimiter, @List + @Delimiter, Number) - Number)))
    FROM (SELECT ROW_NUMBER() OVER (ORDER BY s1.[object_id])
        FROM sys.all_objects AS s1 CROSS APPLY sys.all_objects) AS n(Number)
    WHERE Number <= CONVERT(INT, LEN(@List))
        AND SUBSTRING(@Delimiter + @List, Number, 1) = @Delimiter
    ) AS y);
GO

ここここ、および最初に分割するよりも優れたアプローチについては、ここでいくつか説明しました。

これで、次の方法で簡単に推定できます。

SELECT s.[message-id], f.Item
  FROM dbo.SourceData AS s
  CROSS APPLY dbo.SplitStrings(s.[recipient-address], ';') as f;

また、列名にダッシュを入れないことをお勧めします。それはあなたが常にそれらを入れなければならないことを意味します[square brackets].

于 2012-06-13T15:31:36.217 に答える