2010-04-08 12 views
5

Sto provando a caricare grandi quantità di dati nel server SQL da un file flat utilizzando BULK INSERT. Tuttavia, il mio file ha un numero variabile di colonne, ad esempio la prima riga contiene 14 e la seconda contiene 4. Va bene, voglio solo creare una tabella con il numero massimo di colonne e caricare il file con NULL per il colonne mancanti. Posso giocare con esso da quel punto. Ma sembra che SQL Server, quando raggiunge la fine della riga e abbia più colonne da riempire per quella stessa riga nella tabella di destinazione, passa alla riga successiva e tenta di mettere i dati su quella riga nella colonna sbagliata di la tavola.BULK INSERT con numero incoerente di colonne

C'è un modo per ottenere il comportamento che sto cercando? C'è un'opzione che posso usare per specificare questo? È già successo a qualcuno?

Ecco il codice

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

risposta

3

BULK INSERT non è particolarmente flessibile. Una soluzione consiste nel caricare ogni riga di dati in una tabella temporanea contenente una singola grande colonna varchar. Una volta caricato, si analizza ogni riga utilizzando le proprie routine.

0

Prova a specificare una terminazione della riga con il vostro campo di terminazione.

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

Ulteriori informazioni possono essere trovate qui:

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

+1

Semplicemente non funziona con numero di colonne variabile – gbn

1

Il numero variabile di colonne significa che non può essere analizzato dal codice inserimento di massa. Come fa a sapere il numero corretto di colonne? Cosa succede se ne fornite troppi?

Dovrete caricarlo su un tavolo con 4 colonne, e dividere il resto più tardi (o una grande colonna) o pre-processo per generare un numero uguale di colonne.

2

Un'altra soluzione consiste nel pre-elaborare il file. Potrebbe essere più semplice scrivere un piccolo programma standalone per aggiungere terminatori a ciascuna riga in modo che possa essere caricato correttamente BULK piuttosto che analizzare le righe usando T-SQL.

Ecco un esempio in VB6/VBA. Non è certamente veloce come l'inserto di massa di SQL Server, ma ha solo preelaborato 91000 righe in 10 secondi.

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

mia soluzione (testate in T-SQL):

  1. Crea una tabella con conteggio colum = numero minimo di colonna del file di importazione
  2. Run inserimento di massa (che avrà successo ora)

In ultima colonna della tabella, troverete tutti gli articoli di riposo (incluso il separatore voce)

Se è necessario, creare un'altra tabella a colonne complete, copiare tutte le colonne dalla prima tabella e analizzare solo l'ultima colonna.

file di esempio

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

sarà simile a questa nella tabella:

c1  | c2  | c3 
"alpha" | "beta" | "gamma" 
"one" | "two" | "three , four" 
Problemi correlati