BULK INSERT列数不一致

时间:2010-04-08 17:09:52

标签: sql-server tsql sql-server-2008

我正在尝试使用BULK INSERT从平面文件加载SQL服务器中的大量数据。但是,我的文件具有不同数量的列,例如第一行包含14,第二行包含4.这没关系,我只想创建一个具有最大列数的表,并将文件加载到其中,其中包含NULL缺少列。从那时起我就可以玩它。但似乎SQL Server在到达行尾并且有更多列填充目标表中的同一行时,只是转到下一行并尝试将该行上的数据放到错误的列中桌子。

有没有办法获得我正在寻找的行为?有没有可以用来指定它的选项?有没有人遇到过这个?

这是代码

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

5 个答案:

答案 0 :(得分:5)

BULK INSERT不是特别灵活。一种解决方法是将每行数据加载到包含单个大varchar列的临时表中。加载后,然后使用自己的例程解析每一行。

答案 1 :(得分: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 :(得分:2)

我的解决方法(在T-SQL中测试):

  1. 使用colum count =导入文件的最小列数创建表
  2. 运行批量插入(现在会成功)
  3. 在上一个表格列中,您会找到所有其他项目(包括您的项目分隔符)

    如果您需要,请创建另一个完整列表,从第一个表复制所有列,并仅在最后一列上进行一些解析。

    示例文件

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

    在您的表格中将如下所示:

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

答案 3 :(得分:1)

不同数量的列意味着批量插入代码无法解析它。 它如何知道正确的列数?如果供应太多会怎么样?

你必须将它上传到一个包含4列的表中,然后将其余部分(或一个大列)拆分出来 或者预先处理它以生成相同数量的列。

答案 4 :(得分:-1)

尝试指定ROW终止符以及字段终止符。

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