ОБЪЕМНАЯ ВСТАВКА с непоследовательным количеством столбцов - PullRequest
6 голосов
/ 08 апреля 2010

Я пытаюсь загрузить большой объем данных на сервер SQL из плоского файла с помощью BULK INSERT. Тем не менее, мой файл имеет различное количество столбцов, например, первая строка содержит 14, а вторая содержит 4. Это нормально, я просто хочу создать таблицу с максимальным количеством столбцов и загрузить в нее файл с NULL для пропущенные столбцы. Я могу играть с этим с этого момента. Но кажется, что SQL Server, достигнув конца строки и имея больше столбцов для заполнения этой же строки в таблице назначения, просто переходит на следующую строку и пытается поместить данные в этой строке в неправильный столбец стол.

Есть ли способ получить поведение, которое я ищу? Есть ли вариант, который я могу использовать, чтобы указать это? Кто-нибудь сталкивался с этим раньше?

Вот код

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

Ответы [ 5 ]

5 голосов
/ 09 апреля 2010

BULK INSERT не особенно гибок. Один из способов - загрузить каждую строку данных во временную таблицу, содержащую один большой столбец varchar. После загрузки вы затем анализируете каждую строку, используя свои собственные процедуры.

2 голосов
/ 27 марта 2012

Мой обходной путь (проверено в T-SQL):

  1. Создать таблицу с количеством столбцов = минимальное количество столбцов вашего файла импорта
  2. Запустить массовую вставку (теперь это удастся)

В последнем столбце таблицы вы найдете все остальные элементы (включая разделитель элементов)

Если вам это необходимо, создайте другую таблицу с полным столбцом, скопируйте все столбцы из первой таблицы и выполните анализ только по последнему столбцу.

Файл примера

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

будет выглядеть в вашей таблице следующим образом:

c1      | c2     | c3
"alpha" | "beta" | "gamma"
"one"   | "two"  | "three , four"
2 голосов
/ 28 января 2011

Другой обходной путь - предварительная обработка файла. Может быть проще написать небольшую автономную программу для добавления терминаторов в каждую строку, чтобы ее можно было ЗАГРУЗИТЬ правильно, чем для анализа строк с помощью T-SQL.

Вот один пример в VB6 / VBA. Это, конечно, не так быстро, как массовая вставка SQL Server, но он просто обработал 91000 строк за 10 секунд.

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
1 голос
/ 08 апреля 2010

Различное количество столбцов означает, что он не может быть проанализирован с помощью кода массовой вставки. Как он знает правильное количество столбцов? Что если вы поставите слишком много?

Вам нужно будет загрузить его в таблицу с 4 столбцами, а остальные разделить позже (или в один большой столбец). Или предварительно обработайте его, чтобы сгенерировать равное количество столбцов.

0 голосов
/ 08 апреля 2010

Попробуйте указать терминатор 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...