2012-06-13 32 views
12

Burada bazı tavsiyelerde bulunmak istiyorum, bazı arka plan bilgileri vermek için Exchange 2007'den Message Tracking günlüklerini SQL'e eklemek için çalışıyorum. Günde milyonlarca satırlık milyonlarca değere sahip olduğumuzdan, verileri bir SQL tablosuna eklemek için bir Toplu Ekleme ifadesi kullanıyorum.Bir SQL sütunundaki ayrılmış değerlerin birden çok satır halinde bölünmesi

Aslında, Toplu Tabloyu bir geçici tabloya ekledikten sonra veriyi canlı tabloya BİRLEŞTİRMEKTEDİR, bu, belirli alanlar aksi halde tırnak işaretleri gibi değerler ayrıştırmak gibi test ayrıştırma sorunları içindir.

Alıcı adres sütununun, aşağıdakiler tarafından ayrılmış bir ayrılmış alan olması durumu hariç, bu iyi çalışır; karakteri ve birçok e-posta alıcısı olabileceği gibi bazen çok uzun olabilir.

Bu sütunu almak ve değerleri daha sonra başka bir tabloya eklenecek birden çok satıra ayırmak istiyorum. Sorun, denediğim bir şey ya çok uzun sürüyor ya da istediğim şekilde çalışmıyor.

message-id            recipient-address 
[email protected] [email protected] 
[email protected]  [email protected] 
4fd70c47.4d6[email protected]    [email protected] 
[email protected]    [email protected] 
[email protected]    [email protected] 

kimse bunu hakkında gitmek nasıl hakkında herhangi bir fikir var mı:

message-id            recipient-address 
[email protected] [email protected] 
[email protected]  [email protected] 
[email protected]    [email protected];[email protected];[email protected] 

benim Alıcılar tabloda izlenen bu biçimlendirilmiş istiyorum:

bu örnek verilerini alın ?

PowerShell'i oldukça iyi biliyorum, bu yüzden bunu denedim, ancak 28K kayıtlarında bile bir foreach döngüsünü sonsuza dek sürdürebildi, mümkün olduğunca hızlı/verimli çalışacak bir şeye ihtiyacım var.

Teşekkürler!

+0

Sanırım bir bölme işlevi kullanarak bir tabloya üç sonuç vermelisiniz Buna bak: http: // stackoverflow.com/questions/314824/t-sql-karşı-string-birleştirme-nasıl-split-string-into-multiple-reco Ve bundan sonra sonuç elde etmek için diğer tabloya bölünmüş veri katılmak için yönetebilirsiniz – GregM

cevap

41

Birincisi, bölünmüş işlevi oluşturun:

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 

Artık tarafından basitçe tahmin edebilir: Sütun adlarında

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

Ayrıca ben koyarak değil öneririz tire. Bu, onları her zaman [square brackets]'a koymanız gerektiği anlamına gelir.

+2

Siz efendim, bir internet çerezini hak ediyorum :) Birkaç değişiklik yapmam gerekti, PowerShell öğesi adı sevmediğinden, bunun yerine Ürün alanı Değeri'ni çağırmak zorunda kaldım. Ayrıca, f.item/f.value çağrısının böylelikle bu bölümün takma isminin çalışmasını müteakip CROSS UYGULAMASI'ndan sonra 'AS f' eklemem gerekiyordu. – HungryHippos

+0

Ayrıca sütun isimleri hakkında sizi duyuyoruz, bu sadece takip günlüğü sütun isimleri ile parite tutmak için yapıldı, parantez ihtiyacının farkındayım ve sorun değil. – HungryHippos

+0

briliant örneği. Açıklama şunun gibi görünüyor: SELECT s.item, f.Item dbconfig AS s CROSS APPLY SplitStrings (s.setting, ';') AS f WHERE s.item = 'EXE_PATHS' –

0

SQL Server 2016, önceki çözüme benzer yeni bir tablo işlevi olan string_split() içerir.

tek koşul 130 (SQL Server 2016)

0

Sen (yukarıdaki SQL Server 2005'te kullanılabilir ve) CROSS APPLY kullanabilir ve (SQL Server yukarıda 2016 ve mevcut) STRING_SPLIT işleve uyumluluk düzeyini ayarlama edilir:

DECLARE @delimiter nvarchar(255) = ';'; 

-- create tables 
CREATE TABLE MessageRecipients (MessageId int, Recipients nvarchar(max)); 
CREATE TABLE MessageRecipient (MessageId int, Recipient nvarchar(max)); 

-- insert data 
INSERT INTO MessageRecipients VALUES (1, '[email protected]; [email protected]; [email protected]'); 
INSERT INTO MessageRecipients VALUES (2, '[email protected]; [email protected]'); 

-- insert into MessageRecipient 
INSERT INTO MessageRecipient 
SELECT MessageId, ltrim(rtrim(value)) 
FROM MessageRecipients 
CROSS APPLY STRING_SPLIT(Recipients, @delimiter) 

-- output results 
SELECT * FROM MessageRecipients; 
SELECT * FROM MessageRecipient; 

-- delete tables 
DROP TABLE MessageRecipients; 
DROP TABLE MessageRecipient; 

Sonuçlar:

MessageId Recipients 
----------- ---------------------------------------------------- 
1   [email protected]; [email protected]; [email protected] 
2   [email protected]; [email protected] 

ve

MessageId Recipient 
----------- ---------------- 
1   [email protected] 
1   [email protected] 
1   [email protected] 
2   [email protected] 
2   [email protected] 
İlgili konular