sql >> Database >  >> RDS >> Sqlserver

hoe CSV-gegevens te splitsen en in te voegen in een nieuwe tabel in een enkele instructie?

Je hebt een manier nodig om de string in TSQL te splitsen en te verwerken, er zijn veel manieren om dit te doen. Dit artikel behandelt de voor- en nadelen van zowat elke methode:

Arrays en lijsten in SQL Server 2005 en verder

U moet een splitfunctie maken. Zo kan een splitsingsfunctie worden gebruikt:

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

Ik geef de voorkeur aan de getallentabel om een ​​string in TSQL te splitsen - met behulp van een Tabel met getallen maar er zijn talloze manieren om strings in SQL Server te splitsen, zie de vorige link, waarin de voor- en nadelen van elk worden uitgelegd.

Om de Numbers Table-methode te laten werken, moet u deze eenmalige tijdtabelconfiguratie uitvoeren, waardoor een tabel Numbers wordt gemaakt die rijen van 1 tot 10.000 bevat:

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)

Zodra de Numbers-tabel is ingesteld, maakt u deze splitsfunctie:

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 

U kunt nu eenvoudig een CSV-tekenreeks in een tabel splitsen en eraan deelnemen:

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

UITGANG:

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

(4 row(s) affected)

om je nieuwe tafel te maken, gebruik dit:

--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

UITGANG:

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

(6 row(s) affected)

als u geen Numbers-tabel wilt maken en SQL Server 2005 en hoger gebruikt, kunt u deze splitsfunctie gebruiken (geen Numbers-tabel vereist):

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


  1. MySQL upsert (OP DUPLICATE KEY) met behulp van JDBC Prepared Statement

  2. gevent en posgres:asynchrone verbinding mislukt

  3. MYSQL-UPDATE met IN en subquery

  4. mysql Toegang geweigerd voor gebruiker [e-mail beveiligd] (met wachtwoord:NEE) ondanks het instellen van een wachtwoord en het invoeren in de verbinding uri