it-swarm.com.de

Aufteilen von begrenzten Werten in einer SQL-Spalte in mehrere Zeilen

Ich hätte gerne einige Ratschläge, um einige Hintergrundinformationen zu geben, die ich mit dem Einfügen von Message Tracking-Protokollen aus Exchange 2007 in SQL arbeite. Da wir Millionen von Millionen Zeilen pro Tag haben, verwende ich eine Bulk-Insert-Anweisung, um die Daten in eine SQL-Tabelle einzufügen.

Tatsächlich füge ich Bulk in eine temporäre Tabelle ein und füge die Daten von dort in die Live-Tabelle zusammen. Dies ist für die Analyse von Problemen gedacht, da bestimmte Felder ansonsten Anführungszeichen und ähnliches enthalten.

Dies funktioniert gut, mit der Ausnahme, dass es sich bei der Empfänger-Adressspalte um ein durch a getrenntes Feld handelt. Charakter, und es kann manchmal unglaublich lang sein, da es viele E-Mail-Empfänger geben kann.

Ich möchte diese Spalte nehmen und die Werte in mehrere Zeilen aufteilen, die dann in eine andere Tabelle eingefügt werden. Problem ist alles, was ich versuche, entweder zu lange dauert oder nicht so arbeitet, wie ich es will.

Nehmen Sie diese Beispieldaten:

message-id                                              recipient-address
[email protected]   [email protected]
[email protected]erver.com     [email protected]
[email protected]              [email protected];[email protected];[email protected]

Ich möchte, dass dies in meiner Empfängertabelle wie folgt formatiert wird:

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 eine Idee, wie ich das machen kann?

Ich kenne PowerShell ziemlich gut, also habe ich es versucht, aber eine Foreach-Schleife, selbst für 28K-Datensätze, dauerte ewig, und ich brauche etwas, das so schnell/effizient wie möglich läuft.

Vielen Dank!

13
HungryHippos

Erstellen Sie zuerst 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 einfach extrapolieren durch:

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

Ich schlage auch vor, keine Striche in Spaltennamen zu setzen. Das bedeutet, dass Sie sie immer in [square brackets] eingeben müssen.

45
Aaron Bertrand

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

Die einzige Voraussetzung ist: Kompatibilitätsstufe auf 130 setzen (SQL Server 2016)

3
Oscar Perez

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

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]
1
Alex Vazhev