2016-03-21 11 views
3

Ich bin bulk Einfügen einer CSV-Datei in SQL Server 2012. Die Daten sind derzeit | Pipe als eine lange Zeichenfolge für jede Zeile getrennt. Ich möchte die Daten in die verschiedenen Spalten an jeder Pipe trennen.SQL - Separate Zeichenfolge in Spalten

Hier ist, wie die Daten sieht aus, als seine importiert:

ID|ID2|Person|Person2|City|State 
"1"|"ABC"|"Joe"|"Ben"|"Boston"|"MA" 
"2"|"ABD"|"Jack"|"Tim"|"Nashua"|"NH" 
"3"|"ADC"|"John"|"Mark"|"Hartford"|"CT" 

Ich würde liek die Daten in den Spalten an jedem Rohr zu trennen:

ID ID2 Person Person2 City State 
1 ABC Joe  Ben Boston MA 
2 ABD Jack Tim Nashua NH 
3 AFC John Mark Hartford CT 

ich es schwierig zu finden bin zu Verwenden Sie charindex and substring functions wegen der Anzahl der Spalten der Daten auch ich habe versucht, ParseName zu verwenden, da das eine 2012-Funktion ist, aber das funktioniert nicht, da alle Spalten als NULL mit ParseName

herauskommen

Die Datei enthält etwa 300k Zeilen und ich habe eine Lösung mit XMLName gefunden, aber es ist sehr langsam. dh: dauert eine Minute, um die Daten zu trennen.

Hier ist die langsame xml Lösung:

CREATE TABLE #tbl(iddata varchar(200)) 

DECLARE @i int = 0 
WHILE @i < 100000 
BEGIN 

SET @i = @i + 1 

INSERT INTO #tbl(iddata) 
SELECT '"1"|"ABC"|"Joe"|"Ben"|"Boston"|"MA"' 
UNION ALL 
SELECT '"2"|"ABD"|"Jack"|"Tim"|"Nashua"|"NH"' 
UNION ALL 
SELECT '"3"|"AFC"|"John"|"Mark"|"Hartford"|"CT"' 


END 


;WITH XMLData 
AS 
(
    SELECT idData, 
    CONVERT(XML,'<IDs><id>' 
    + REPLACE(iddata,'|', '</id><id>') + '</id></IDs>') AS xmlname 
     FROM (
      SELECT REPLACE(iddata,'"','') as iddata 
      FROM #tbl 
      )x 
) 

SELECT xmlname.value('/IDs[1]/id[1]','varchar(100)') AS ID, 
     xmlname.value('/IDs[1]/id[2]','varchar(100)') AS ID2, 
     xmlname.value('/IDs[1]/id[3]','varchar(100)') AS Person, 
     xmlname.value('/IDs[1]/id[4]','varchar(100)') AS Person2, 
     xmlname.value('/IDs[1]/id[5]','varchar(100)') AS City, 
     xmlname.value('/IDs[1]/id[6]','varchar(100)') AS State 
FROM XMLData 
+0

Diese Fragen enthält alles, was eine gute Frage braucht: copy'n'pasteable Testdaten, Eingabe, erwartete Ausgabe, eigener Versuch und eine klare Frage. Upvote von meiner Seite – Shnugo

Antwort

2

Dies wird es für Sie tun.

CREATE TABLE #Import (
      ID NVARCHAR(MAX), 
      ID2 NVARCHAR(MAX), 
      Person NVARCHAR(MAX), 
      Person2 NVARCHAR(MAX), 
      City NVARCHAR(MAX), 
      State NVARCHAR(MAX)) 

     SET QUOTED_IDENTIFIER OFF 

     BULK INSERT #Import 
     FROM 'C:\MyFile.csv' 
     WITH 
     (
      FIRSTROW = 2, 
      FIELDTERMINATOR = '|', 
      ROWTERMINATOR = '\n', 
      ERRORFILE = 'C:\myRubbishData.log' 
     ) 

     select * from #Import 
     DROP TABLE #Import 

Leider BULK INSERT nicht mit Texterkennungszeichen behandeln, so dass Sie mit „ABC“ am Ende statt ABC.

Entfernen Sie entweder die Textkennzeichner aus der CSV-Datei oder führen Sie nach dem Importieren der Daten eine Ersetzung in der Tabelle aus.

+0

Sie könnten eine Formatdatei verwenden, um die Textkennzeichner anzugeben. –

1

Um Ihnen den Schmerz und das Elend zu ersparen mit Rohren beschäftigen, würde ich empfehlen, dass Sie Ihre Eingabedatei verarbeiten diese Rohre in Kommas, zu konvertieren und dann Verwenden Sie die integrierte SQL Server-Kapazität zum Analysieren von CSV in einer Tabelle.

Wenn Sie Java verwenden, würden die Rohre zu ersetzen buchstäblich nur eine Zeile Code nehmen:

String line = "\"1\"|\"ABC\"|\"Joe\"|\"Ben\"|\"Boston\"|\"MA\""; 
line = line.replaceAll("|", ","); 
// then write this line back out to file 

BULK INSERT YourTable 
FROM 'input.csv' 
WITH 
(
    FIRSTROW = 2, 
    FIELDTERMINATOR = ',', 
    ROWTERMINATOR = '\n', 
    ERRORFILE = 'C:\CSVDATA\SchoolsErrorRows.csv', 
    TABLOCK 
) 
0

Wenn Sie nicht arbeiten mit den BULK Vorschläge (wegen Rechte) Sie können Ihre Abfrage beschleunigen damit um etwa 30% bis:

SELECT AsXml.value('x[1]','varchar(100)') AS ID 
     ,AsXml.value('x[2]','varchar(100)') AS ID2 
     ,AsXml.value('x[3]','varchar(100)') AS Person 
     ,AsXml.value('x[4]','varchar(100)') AS Person2 
     ,AsXml.value('x[5]','varchar(100)') AS City 
     ,AsXml.value('x[6]','varchar(100)') AS State 
FROM #tbl 
CROSS APPLY(SELECT CAST('<x>' + REPLACE(SUBSTRING(iddata,2,LEN(iddata)-2),'"|"','</x><x>') + '</x>' AS XML)) AS a(AsXml) 
Verwandte Themen