2010-04-08 10 views
5

Ich versuche, eine große Menge Daten in SQL Server von einer flachen Datei mit BULK INSERT zu laden. Meine Datei hat jedoch eine unterschiedliche Anzahl von Spalten, zum Beispiel die erste Zeile enthält 14 und die zweite enthält 4. Das ist in Ordnung, ich möchte nur eine Tabelle mit der maximalen Anzahl von Spalten erstellen und die Datei mit NULL für die Datei laden fehlende Spalten. Ich kann damit spielen. Aber es scheint, dass SQL Server, wenn das Ende der Zeile erreicht und mehr Spalten für die gleiche Zeile in der Zieltabelle zu füllen hat, nur in die nächste Zeile weitergeht und versucht, die Daten in dieser Zeile in die falsche Spalte von Der Tisch.BULK INSERT mit inkonsistenter Anzahl von Spalten

Gibt es eine Möglichkeit, das von mir gesuchte Verhalten zu erhalten? Gibt es eine Option, die ich verwenden kann, um dies zu spezifizieren? Ist schon mal jemand darauf gestoßen?

Hier ist der Code

BULK INSERT #t 
FROM '<path to file>' 
WITH 
(
    DATAFILETYPE = 'char', 
    KEEPNULLS, 
    FIELDTERMINATOR = '#' 
) 

Antwort

3

BULK INSERT ist nicht besonders flexibel. Ein Problem besteht darin, jede Datenzeile in eine Zwischentabelle zu laden, die eine einzelne große varchar-Spalte enthält. Nach dem Laden analysieren Sie dann jede Zeile mit Ihren eigenen Routinen.

0

versuchen, eine Zeile Terminator zusammen mit Ihrem Feldabschluss angeben.

BULK INSERT #t 
FROM '<path to file>' 
WITH 
( 
    DATAFILETYPE = 'char', 
    KEEPNULLS, 
    FIELDTERMINATOR = '#', 
    ROWTERMINATOR = '\n' --Or whatever signifies the end of a row in your flatfile. 
) 

Mehr Informationen dazu finden Sie hier:

http://msdn.microsoft.com/en-us/library/ms191485.aspx

+1

einfach nicht mit unterschiedlicher Anzahl von Spalten arbeiten – gbn

1

Die unterschiedliche Anzahl der Spalten bedeutet, es kann nicht durch den Masseneinfügungs Code analysiert werden. Woher weiß es die richtige Anzahl von Spalten? Was ist, wenn Sie zu viele liefern?

Sie müssen es in eine Tabelle mit 4 Spalten hochladen, und den Rest später spalten (oder eine große Spalte) Oder vorverarbeiten, um eine gleiche Anzahl von Spalten zu erzeugen.

2

Eine andere Problemumgehung besteht darin, die Datei vorzuverarbeiten. Es kann einfacher sein, ein kleines Standalone-Programm zu schreiben, um Terminatoren zu jeder Zeile hinzuzufügen, damit BULK korrekt geladen werden kann, als die Zeilen mit T-SQL zu analysieren.

Hier ist ein Beispiel in VB6/VBA. Es ist sicherlich nicht so schnell wie die SQL Server-Masseneinfügung, aber es hat nur 91000 Zeilen in 10 Sekunden vorverarbeitet.

Sub ColumnDelimiterPad(FileName As String, OutputFileName As String, ColumnCount As Long, ColumnDelimiter As String, RowDelimiter As String) 
    Dim FileNum As Long 
    Dim FileData As String 

    FileNum = FreeFile() 
    Open FileName For Binary Access Read Shared As #FileNum 
    FileData = Space$(LOF(FileNum)) 
    Debug.Print "Reading File " & FileName & "..." 
    Get #FileNum, , FileData 
    Close #FileNum 

    Dim Patt As VBScript_RegExp_55.RegExp 
    Dim Matches As VBScript_RegExp_55.MatchCollection 

    Set Patt = New VBScript_RegExp_55.RegExp 
    Patt.IgnoreCase = True 
    Patt.Global = True 
    Patt.MultiLine = True 
    Patt.Pattern = "[^" & RowDelimiter & "]+" 
    Debug.Print "Parsing..." 
    Set Matches = Patt.Execute(FileData) 

    Dim FileLines() As String 
    Dim Pos As Long 
    Dim MissingDelimiters 

    ReDim FileLines(Matches.Count - 1) 
    For Pos = 0 To Matches.Count - 1 
     If (Pos + 1) Mod 10000 = 0 Then Debug.Print Pos + 1 
     FileLines(Pos) = Matches(Pos).Value 
     MissingDelimiters = ColumnCount - 1 - Len(FileLines(Pos)) + Len(Replace(FileLines(Pos), ColumnDelimiter, "")) 
     If MissingDelimiters > 0 Then FileLines(Pos) = FileLines(Pos) & String(MissingDelimiters, ColumnDelimiter) 
    Next 
    If (Pos + 1) Mod 10000 <> 0 Then Debug.Print Pos + 1 

    If Dir(OutputFileName) <> "" Then Kill OutputFileName 
    Open OutputFileName For Binary Access Write Lock Read Write As #FileNum 
    Debug.Print "Writing " & OutputFileName & "..." 
    Put #FileNum, , Join(FileLines, RowDelimiter) 
    Close #FileNum 
    Debug.Print "Done." 
End Sub 
2

Meine Abhilfe (in T-SQL getestet):

  1. minimale Spaltenanzahl Ihrer Importdatei
  2. Run Bulk-Einsatz (es gelingen wird jetzt) ​​erstellen Tabelle mit colum count =

In den letzten Tabellenspalte finden Sie alle übrigen Elemente (einschließlich Ihrer Artikel Separator) finden

Wenn es für Sie erforderlich ist, erstellen Sie eine weitere voll-columned Tabelle, kopieren Sie alle Spalten aus der ersten Tabelle, und führen Sie einige Parsing nur über die letzte Spalte.

Beispieldatei

alpha , beta , gamma 
one , two , three , four 

wird wie folgt in der Tabelle aussehen:

c1  | c2  | c3 
"alpha" | "beta" | "gamma" 
"one" | "two" | "three , four" 
Verwandte Themen