2010-04-08 9 views
5

J'essaye de charger une grande quantité de données dans le serveur SQL à partir d'un fichier plat en utilisant BULK INSERT. Cependant, mon fichier a un nombre variable de colonnes, par exemple la première ligne contient 14 et la seconde contient 4. C'est OK, je veux juste faire une table avec le nombre maximum de colonnes et charger le fichier avec des valeurs NULL pour le colonnes manquantes. Je peux jouer avec à partir de ce moment. Mais il semble que SQL Server, lorsqu'il atteint la fin de la ligne et qu'il ait plus de colonnes à remplir pour cette même ligne dans la table de destination, passe juste à la ligne suivante et tente de placer les données sur cette ligne dans la mauvaise colonne la table.BULK INSERT avec nombre de colonnes incohérent

Existe-t-il un moyen d'obtenir le comportement que je recherche? Y a-t-il une option que je peux utiliser pour le spécifier? Quelqu'un at-il déjà rencontré cela?

Voici le code

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

Répondre

3

L'INSERT EN VRAC n'est pas particulièrement flexible. Une solution consiste à charger chaque ligne de données dans une table temporaire contenant une seule grande colonne varchar. Une fois chargé, vous devez ensuite analyser chaque ligne en utilisant vos propres routines.

0

Essayez spécifier une fin de ligne avec votre fin de champ.

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

Plus d'informations sur ce qui peut être trouvé ici:

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

+1

ne fonctionnera pas avec un nombre variable de colonnes – gbn

1

Le nombre variable de colonnes signifie qu'il ne peut pas être analysé par le code d'insertion en bloc. Comment connaît-il le bon nombre de colonnes? Que faire si vous en fournissez trop?

Vous devrez le télécharger dans une table avec 4 colonnes, et diviser le reste plus tard (ou une grande colonne) Ou prétraitez-le pour générer un nombre égal de colonnes.

2

Une autre solution consiste à pré-traiter le fichier. Il peut être plus facile d'écrire un petit programme autonome pour ajouter des terminaisons à chaque ligne afin de pouvoir charger BULK correctement que d'analyser les lignes en utilisant T-SQL.

Voici un exemple dans VB6/VBA. Il n'est certainement pas aussi rapide que l'insertion en bloc de SQL Server, mais il a juste prétraité 91 000 lignes en 10 secondes.

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

Ma solution (testé dans T-SQL):

  1. Créer table avec le nombre de Colum = nombre de colonnes minimum de votre fichier d'importation
  2. Run insert en vrac (il réussira maintenant)

Dans la dernière colonne du tableau, vous trouverez tous les éléments de repos (y compris votre séparateur d'article)

Si cela vous est nécessaire, créez une autre table à colonnes complètes, copiez toutes les colonnes de la première table et effectuez une analyse uniquement sur la dernière colonne.

fichier Exemple

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

ressemblera à ceci dans votre table:

c1  | c2  | c3 
"alpha" | "beta" | "gamma" 
"one" | "two" | "three , four" 
Questions connexes