2012-06-13 14 views
12

Ich möchte hier einen Ratschlag geben, um einige Hintergrundinformationen zu geben. Ich arbeite mit dem Einfügen von Nachrichtenverfolgungsprotokollen aus Exchange 2007 in SQL. Da wir Millionen von Millionen Zeilen pro Tag haben, verwende ich eine Bulk Insert-Anweisung, um die Daten in eine SQL-Tabelle einzufügen.Getrennte Werte in einer SQL-Spalte in mehrere Zeilen teilen

In der Tat habe ich tatsächlich Bulk Insert in eine temporäre Tabelle und dann von dort MERGE ich die Daten in die Live-Tabelle, dies ist für Test Parsing Probleme wie bestimmte Felder haben sonst Anführungszeichen und so um die Werte.

Dies funktioniert gut, mit Ausnahme der Tatsache, dass die Spalte Empfängeradresse ein abgegrenztes Feld ist, das durch a getrennt ist; Charakter, und es kann manchmal unglaublich lang sein, da es viele E-Mail-Empfänger geben kann.

Ich möchte diese Spalte nehmen, und teilen Sie die Werte in mehrere Zeilen, die dann in eine andere Tabelle eingefügt werden würde. Das Problem ist, dass alles, was ich versuche, entweder zu lange dauert oder nicht so funktioniert, wie ich es möchte.

dieses Beispiel Daten Nehmen:

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

Das möchte ich in meinem Empfänger Tabelle wie folgt formatiert werden:

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

Hat jemand irgendwelche Ideen, wie ich über das tun dies gehen kann ?

Ich kenne PowerShell ziemlich gut, also habe ich versucht, aber eine foreach-Schleife sogar auf 28K-Records dauerte ewig, ich brauche etwas, das so schnell/effizient wie möglich ausgeführt wird.

Danke!

+0

Ich denke, Sie sollten Sie drei Ergebnisse in eine Tabelle mit einer Split-Funktion setzen Sieh dir das an: http: // stackoverflow.com/questions/314824/t-sql-gegenüber-zu-string-verketten-how-to-strip-string-in-multiple-reco Und danach können Sie Ihre geteilten Daten in Ihrer anderen Tabelle zu verbinden, um Ihr Ergebnis zu erhalten – GregM

Antwort

41

Erstellen Sie zunächst eine Split-Funktion:

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 

Jetzt können Sie extrapolieren einfach durch:

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

Auch schlage ich keine Bindestriche in Spaltennamen setzen. Es bedeutet, dass Sie sie immer in [square brackets] setzen müssen.

+2

Sie, Sir, verdienen einen Internet-Cookie :) Ich musste ein paar Änderungen vornehmen, ich musste stattdessen das Feld Wert des Artikels aufrufen, da PowerShell den Namen Item nicht mochte. Ich musste auch 'AS f' nach dem CROSS APPLY hinzufügen, um diesen Abschnitt zu aliasieren, so dass f.item/f.value aufgerufen wurde. – HungryHippos

+0

Auch hören Sie über die Spaltennamen, dies wurde getan, nur um Parität mit den Tracking-Log-Spaltennamen selbst zu halten, ich bin mir der Notwendigkeit für Klammern und es ist in Ordnung. – HungryHippos

+0

brillante Probe. meine Aussage sieht so aus: SELECT s.item, f.Item FROM dbconfig AS s CROSS APPLY SplitStrings (s.Einstellung, ';') AS f WHERE s.item = 'EXE_PATHS' –

0

SQL Server 2016 enthalten eine neue Tabellenfunktion string_split(), ähnlich der vorherigen Lösung.

Die einzige Voraussetzung ist, Set-Kompatibilitätsgrad auf 130 (SQL Server 2016)

0

Sie können CROSS APPLY (verfügbar in SQL Server 2005 und höher) verwenden und STRING_SPLIT Funktion (verfügbar in SQL Server 2016 und höher):

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; 

Ergebnisse:

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

und

MessageId Recipient 
----------- ---------------- 
1   [email protected] 
1   [email protected] 
1   [email protected] 
2   [email protected] 
2   [email protected] 
Verwandte Themen