2010-04-08 41 views
5

Tôi đang cố gắng tải một lượng lớn dữ liệu trong máy chủ SQL từ một tệp phẳng bằng BULK INSERT. Tuy nhiên, tệp của tôi có số lượng cột khác nhau, ví dụ hàng đầu tiên chứa 14 và cột thứ hai chứa 4. Đó là OK, tôi chỉ muốn tạo một bảng với số cột tối đa và tải tệp vào đó bằng NULL cho thiếu cột. Tôi có thể chơi với nó từ thời điểm đó. Nhưng có vẻ như SQL Server, khi đến cuối dòng và có nhiều cột để điền vào cùng hàng đó trong bảng đích, chỉ cần chuyển sang dòng tiếp theo và cố gắng đặt dữ liệu trên dòng đó vào cột sai của cai ban.BULK INSERT với số lượng cột không nhất quán

Có cách nào để có được hành vi mà tôi đang tìm kiếm không? Có một tùy chọn mà tôi có thể sử dụng để xác định điều này? Có ai chạy vào điều này trước đây không?

Đây là mã

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

Trả lời

3

BULK INSERT không đặc biệt linh hoạt. Một công việc xung quanh là tải mỗi hàng dữ liệu vào một bảng tạm thời có chứa một cột varchar lớn duy nhất. Sau khi được tải, sau đó bạn phân tích từng hàng bằng cách sử dụng các thường trình của riêng bạn.

0

Cố gắng xác định một terminator ROW cùng với terminator lĩnh vực của bạn.

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

Thông tin thêm về vấn đề này có thể được tìm thấy ở đây:

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

+1

Đơn giản chỉ cần sẽ không làm việc với số cột khác nhau – gbn

1

Số khác nhau của các cột có nghĩa là nó không thể được phân tích bởi mã chèn số lượng lớn. Làm cách nào để biết số cột chính xác? Nếu bạn cung cấp quá nhiều thì sao?

Bạn sẽ phải tải nó lên bảng có 4 cột và chia phần còn lại sau (hoặc một cột lớn) Hoặc xử lý trước để tạo số cột bằng nhau.

2

Cách giải quyết khác là xử lý trước tệp. Nó có thể dễ dàng hơn để viết một chương trình độc lập nhỏ để thêm các terminator vào mỗi dòng để nó có thể được tải BULK đúng cách để phân tích cú pháp các dòng bằng cách sử dụng T-SQL.

Đây là một ví dụ trong VB6/VBA. Nó chắc chắn không phải là nhanh như chèn số lượng lớn SQL Server, nhưng nó chỉ được xử lý trước 91000 hàng trong 10 giây.

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

workaround của tôi (thử nghiệm trong T-SQL):

  1. Tạo bảng với số cột = count cột tối thiểu của tệp nhập của bạn
  2. Chạy số lượng lớn chèn (nó sẽ thành công bây giờ)

Trong cột cuối cùng, bạn sẽ tìm thấy tất cả các mục còn lại (bao gồm dấu phân cách của bạn)

Nếu cần thiết cho bạn, hãy tạo một bảng có cột đầy đủ khác, sao chép tất cả các cột từ bảng đầu tiên và chỉ thực hiện phân tích cú pháp trên cột cuối cùng.

tập tin Ví dụ

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

sẽ trông như thế này trong bảng của bạn:

c1  | c2  | c3 
"alpha" | "beta" | "gamma" 
"one" | "two" | "three , four" 
Các vấn đề liên quan