Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Wie kann man CSV-Daten in einer einzigen Anweisung aufteilen und in eine neue Tabelle einfügen?

Sie brauchen eine Möglichkeit, die Zeichenfolge in TSQL aufzuteilen und zu verarbeiten, es gibt viele Möglichkeiten, dies zu tun. Dieser Artikel behandelt die Vor- und Nachteile von fast jeder Methode:

Arrays und Listen in SQL Server 2005 und höher

Sie müssen eine Split-Funktion erstellen. So kann eine Split-Funktion verwendet werden:

SELECT
    *
    FROM YourTable                               y
    INNER JOIN dbo.yourSplitFunction(@Parameter) s ON y.ID=s.Value

Ich bevorzuge den Zahlentabellenansatz, um eine Zeichenfolge in TSQL aufzuteilen - Mit a Zahlentabelle aber es gibt zahlreiche Möglichkeiten, Zeichenfolgen in SQL Server aufzuteilen, siehe den vorherigen Link, der die Vor- und Nachteile der einzelnen erklärt.

Damit die Zahlentabellenmethode funktioniert, müssen Sie diese einmalige Zeittabelleneinrichtung durchführen, die eine Tabelle Numbers erstellt die Zeilen von 1 bis 10.000 enthält:

SELECT TOP 10000 IDENTITY(int,1,1) AS Number
    INTO Numbers
    FROM sys.objects s1
    CROSS JOIN sys.objects s2
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number)

Sobald die Numbers-Tabelle eingerichtet ist, erstellen Sie diese Split-Funktion:

CREATE FUNCTION inline_split_me (@SplitOn char(1),@param varchar(7998)) RETURNS TABLE AS
   RETURN(SELECT substring(@SplitOn + @param + ',', Number + 1,
                    charindex(@SplitOn, @SplitOn + @param + @SplitOn, Number + 1) - Number - 1)
                 AS Value
          FROM   Numbers
          WHERE  Number <= len(@SplitOn + @param + @SplitOn) - 1
            AND  substring(@SplitOn + @param + @SplitOn, Number, 1) = @SplitOn)

GO 

Sie können jetzt ganz einfach eine CSV-Zeichenfolge in eine Tabelle aufteilen und ihr beitreten:

select * from dbo.inline_split_me(';','1;22;333;4444;;') where LEN(Value)>0

AUSGABE:

Value
----------------------
1
22
333
4444

(4 row(s) affected)

Um eine neue Tabelle zu erstellen, verwenden Sie Folgendes:

--set up tables:
DECLARE @Documents table (DocumentID varchar(500), SomeValue varchar(5))
INSERT @Documents VALUES ('1,2,3,4','AAA')
INSERT @Documents VALUES ('5,6'    ,'BBBB')

DECLARE @NewDocuments table (DocumentID int, SomeValue varchar(5))

--populate NewDocuments
INSERT @NewDocuments
    (DocumentID, SomeValue)
SELECT
    c.value,a.SomeValue
    FROM @Documents    a
        CROSS APPLY dbo.inline_split_me(',',a.DocumentID) c

 --show NewDocuments contents:
select * from @NewDocuments

AUSGABE:

DocumentID  SomeValue
----------- ---------
1           AAA
2           AAA
3           AAA
4           AAA
5           BBBB
6           BBBB

(6 row(s) affected)

Wenn Sie keine Numbers-Tabelle erstellen möchten und SQL Server 2005 oder höher ausführen, können Sie einfach diese Split-Funktion verwenden (keine Numbers-Tabelle erforderlich):

CREATE FUNCTION inline_split_me (@SplitOn char(1),@String varchar(7998))
RETURNS TABLE AS
RETURN (WITH SplitSting AS
           (SELECT
                LEFT(@String,CHARINDEX(@SplitOn,@String)-1) AS Part
                    ,RIGHT(@String,LEN(@String)-CHARINDEX(@SplitOn,@String)) AS Remainder
                WHERE @String IS NOT NULL AND CHARINDEX(@SplitOn,@String)>0
            UNION ALL
            SELECT
                LEFT(Remainder,CHARINDEX(@SplitOn,Remainder)-1)
                    ,RIGHT(Remainder,LEN(Remainder)-CHARINDEX(@SplitOn,Remainder))
                FROM SplitSting
                WHERE Remainder IS NOT NULL AND CHARINDEX(@SplitOn,Remainder)>0
            UNION ALL
            SELECT
                Remainder,null
                FROM SplitSting
                WHERE Remainder IS NOT NULL AND CHARINDEX(@SplitOn,Remainder)=0
           )
           SELECT Part FROM SplitSting
       )
GO