2010-04-08 85 views
5

我正嘗試使用BULK INSERT從平面文件中加載SQL Server中的大量數據。然而,我的文件有不同數量的列,例如第一行包含14,第二行包含4。這是好的,我只想製作一個最大列數的表,並將文件加載到它的NULL值爲缺少列。從那一點我可以玩。但是,似乎SQL Server在到達行尾並且有更多列填充目標表中的同一行時,會轉移到下一行,並嘗試將該行上的數據放到錯誤的列中桌子。批量插入的列數不一致

有沒有一種方法來獲得我正在尋找的行爲?有沒有我可以用來指定的選項?有沒有人遇到過這個?

下面是代碼

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

回答

3

BULK INSERT不是特別靈活。一種解決方法是將每行數據加載到包含單個大型varchar列的臨時表中。一旦加載,你就可以用你自己的例程來解析每一行。

0

嘗試用你的字段終止沿指定行終止。

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

這個更多信息可以在這裏找到:

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

+1

根本不會有不同的列數工作 – gbn 2010-04-10 08:49:33

1

的不同列數意味着它不能被批量插入的代碼進行解析。 它如何知道正確的列數?如果你供應太多,會怎麼樣?

你必須將它上傳到一個有4列的表格中,並在稍後(或一個大的列)分割出其餘的(或一個大列) 或預處理它以生成相同數量的列。

2

另一個解決方法是預處理文件。編寫一個小的獨立程序來爲每行添加終止符可能更容易,因此它可以正確裝載BULK,而不是使用T-SQL解析行。

下面是VB6/VBA中的一個示例。這當然不像SQL Server批量插入那麼快,但它只是在10秒內預處理了91000行。

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

我的解決方法(在T-SQL測試):

  1. 創建科拉姆數=導入文件的最小列數表
  2. 運行BULK INSERT(現在它將成功)

在上表列,你會發現所有其他項目(包括您的項目分離器)

如果您需要,請創建另一個完整列表,從第一個表中複製所有列,並僅對最後一列進行一些解析。

示例文件

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

看起來像這樣在你的表:

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