7
votes

Insertion en vrac avec nombre incohérent de colonnes

J'essaie de charger une grande quantité de données dans SQL Server à partir d'un fichier plat à l'aide d'un insert en vrac. Cependant, mon fichier comporte un nombre variable de colonnes, par exemple, la première ligne contient 14 et la seconde contient 4. C'est bon, je veux simplement créer une table avec le nombre maximum de colonnes et charger le fichier avec des nulls pour le colonnes manquantes. Je peux jouer avec ça à partir de ce point. Mais il semble que SQL Server, lors de la fin de la ligne et d'avoir plus de colonnes à remplir pour la même ligne de la table de destination, passe simplement sur la ligne suivante et tente de mettre les données sur cette ligne à la mauvaise colonne de La table.

Y a-t-il un moyen d'obtenir le comportement que je cherche? Y a-t-il une option que je peux utiliser pour spécifier cela? Quelqu'un a-t-il couru dans cela avant? P>

Voici le code P>

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


0 commentaires

5 Réponses :


-2
votes

Essayez de spécifier un terminateur de ligne avec votre terminaison 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.
) 


0 commentaires

1
votes

Le nombre de colonnes variables signifie qu'il ne peut pas être analysé par le code d'insertion en vrac. Comment connaît-il le nombre correct de colonnes? Et si vous fournissez trop?

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


0 commentaires

5
votes

L'insert en vrac n'est pas particulièrement flexible. Un travail de travail est de charger chaque ligne de données dans une table provisoire contenant une seule colonne de varcharine. Une fois chargé, vous analysez ensuite chaque ligne en utilisant vos propres routines.


0 commentaires

2
votes

Une autre solution consiste à préproduire le fichier. Il peut être plus facile d'écrire un petit programme autonome pour ajouter des terminateurs à chaque ligne afin qu'il puisse être chargé en vrac correctement que pour analyser les lignes à l'aide de T-SQL.

Voici un exemple dans VB6 / VBA. Ce n'est certainement pas aussi rapide que l'insert en vrac SQL Server, mais il vient de prétraiter 91 000 lignes en 10 secondes. P>

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


0 commentaires

3
votes

ma solution de contournement (testée en T-SQL): strong>

  1. Créer une table avec Colum Nombre = nombre de colonnes minimum de votre fichier d'importation Li>
  2. Run Bulk insert (il réussira maintenant) li> ol>

    Dans la colonne Dernière table, vous trouverez tous les éléments de repos (y compris votre séparateur d'élément) p>

    S'il est nécessaire pour vous, créez une autre table pleine colocolue, copiez toutes les colonnes de la première. Table, et faites des analyses que sur la dernière colonne. p>

    exemple de fichier p> xxx pré>

    ressemblera à ceci dans votre table: p>

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


0 commentaires