2010-04-08 28 views
5

Estoy intentando cargar una gran cantidad de datos en SQL Server desde un archivo plano usando BULK INSERT. Sin embargo, mi archivo tiene un número variable de columnas, por ejemplo, la primera fila contiene 14 y la segunda contiene 4. Eso está bien, solo quiero hacer una tabla con el número máximo de columnas y cargar el archivo con NULL para el columnas faltantes Puedo jugar con eso desde ese punto. Pero parece que SQL Server, al llegar al final de la línea y tener más columnas para llenar para la misma fila en la tabla de destino, simplemente pasa a la siguiente línea e intenta colocar los datos en esa línea en la columna incorrecta de la mesa.BULK INSERT con número incoherente de columnas

¿Hay alguna manera de obtener el comportamiento que estoy buscando? ¿Hay alguna opción que pueda usar para especificar esto? ¿Alguien ha topado con esto antes?

Este es el código

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

Respuesta

3

BULK INSERT no es particularmente flexible. Una solución alternativa es cargar cada fila de datos en una tabla provisional que contenga una única columna varchar grande. Una vez cargado, luego analiza cada fila usando sus propias rutinas.

0

intente especificar un terminador de fila junto con su terminador de campo.

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

Más información sobre esto se puede encontrar aquí:

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

+1

Simplemente no va a funcionar con un número variable de columnas – gbn

1

El número variable de columnas significa que no se puede analizar por el código de inserción masiva. ¿Cómo sabe el número correcto de columnas? ¿Qué pasa si usted proporciona demasiados?

Tendrá que subirlo a una tabla con 4 columnas, y dividir el resto más tarde (o una columna grande) O preprocesarlo para generar el mismo número de columnas.

2

Otra solución es preprocesar el archivo. Puede ser más fácil escribir un pequeño programa independiente para agregar terminadores a cada línea, de modo que se pueda cargar en BULK correctamente, en lugar de analizar las líneas usando T-SQL.

Aquí hay un ejemplo en VB6/VBA. Ciertamente no es tan rápido como la inserción masiva de SQL Server, pero preprocesó 91000 filas en 10 segundos.

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

Mi solución (a prueba en T-SQL):

  1. Crear una tabla con el recuento de Colum = número de columnas mínimo de su archivo de importación
  2. Run inserción masiva (que tendrá éxito ahora)

En la columna última mesa, encontrará todos los artículos del resto (incluyendo el separador de elementos)

Si es necesario para usted, cree otra tabla de columnas completas, copie todas las columnas de la primera tabla y realice algunos análisis solo sobre la última columna.

archivo Ejemplo

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

se verá así en su mesa:

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