Ошибка массовой вставки файла фиксированной ширины SQL Server

#sql #sql-server #bulkinsert

#sql #sql-server #bulkinsert

Вопрос:

Я пытаюсь использовать массовую вставку для загрузки очень большого файла данных (5 строк). Все столбцы — это просто переменные, без преобразования. Таким образом, формат файла прост…

 11.0
29
1   SQLCHAR     0   8   ""  1   AccountId       ""
2   SQLCHAR     0   10  ""  2   TranDate        ""
3   SQLCHAR     0   4   ""  3   TransCode       ""
4   SQLCHAR     0   2   ""  4   AdditionalCode      ""
5   SQLCHAR     0   11  ""  5   CurrentPrincipal    ""
6   SQLCHAR     0   11  ""  6   CurrentInterest     ""
7   SQLCHAR     0   11  ""  7   LateInterest        ""
...
27  SQLCHAR     0   8   ""  27  Operator        ""
28  SQLCHAR     0   10  ""  28  UpdateDate      ""
29  SQLCHAR     0   12  ""  29  TimeUpdated     ""
 

но каждый раз в какой-то момент я получаю одну и ту же ошибку:

Сообщение 4832, уровень 16, состояние 1, строка 1 Массовая загрузка: в файле данных обнаружен неожиданный конец файла. Сообщение об ошибке 7399, уровень 16, состояние 1, строка 1 Поставщик OLE DB «BULK» для связанного сервера «(null)» сообщил об ошибке. Поставщик не предоставил никакой информации об ошибке. Сообщение 7330, уровень 16, состояние 2, строка 1 Не может получить строку от поставщика OLE DB «BULK» для связанного сервера «(null)».

Я попробовал следующее:

 Bulk Insert 
    [TableName] From 'dataFilePPathSpecification'
    With (FORMATFILE = 'formatFilePPathSpecification')
 

но я получаю сообщение об ошибке примерно через 5-6 минут, и данные не были вставлены.

Когда я добавил параметр BatchSize, я получаю сообщение об ошибке через гораздо более длительное время, ближе к концу файла, после того, как все строки, за исключением очень немногих, были вставлены успешно.

 Bulk Insert 
    [TableName] From 'dataFilePPathSpecification'
    With (BATCHSIZE = 200, 
          FORMATFILE = 'formatFilePPathSpecification')
 

Когда я устанавливаю размер пакета на 2000, он выполняется намного быстрее (я предполагаю, что меньше, больше транзакций), но все равно происходит сбой.

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

Ответ №1:

Явно укажите свой завершитель строки:

     BULK INSERT TableName FROM 'Path'
       WITH (
          DATAFILETYPE = 'char',
          ROWTERMINATOR = 'rn'
          With (FORMATFILE = 'formatFilePPathSpecification')
    );
 

Если это по-прежнему не удается, проверьте свой файл, чтобы увидеть, есть ли у вас неожиданные терминаторы, встроенные в текстовые поля.

Комментарии:

1. Мой файл данных был файлом фиксированной ширины, без ограничителей полей, но что вы подразумеваете под line и row терминаторами, это одно и то же, нет? — или вы просто неправильно выразились?

2. так и думал… Тогда вы правы, это исправлено… Но мне пришлось поставить » r n» для строки (последнего поля).

3. Да, во многом зависит от файла, который вы извлекаете. Соответствующим образом обновили ответ..

Ответ №2:

Попытка использовать спецификатор errorFile в части WITH для поиска некорректных данных:

ERRORFILE = ‘C:offendingdata.log ‘

Ответ №3:

Если у вас все еще есть проблема даже после включения вывода errorfile, вы можете выполнить бинарный поиск проблемы, установив параметры firstRow и lastRow и повторно запустив массовую вставку, чтобы изолировать проблему.

Честно говоря, ваш формат ввода выглядит настолько простым, что было бы неплохо написать небольшое приложение на C #, Python или что-то еще, что поддерживает ваше приложение boat, чтобы проверить качество ваших данных перед попыткой импорта. Вы можете просто удалить недопустимые строки (или, возможно, исправить их) или записать их в файл исключений для ручной обработки или просто остановить задание — т.Е. Файл должен быть идеальным, иначе он считается поврежденным. Проверка 5M строк таким образом будет довольно быстрой — по сути, настолько быстрой, насколько вы сможете прочитать файл (и, возможно, записать) файл.

Ответ №4:

Спасибо за предложения всем, я применил обе идеи… Я написал небольшой .Утилита обработки файлов Net (c #) сообщила мне, что в конце каждой строки есть дополнительные нули (двоичные нули ( 0), и я смог удалить их с помощью простой программы на c #.

В файле с ошибкой указано, что проблема была в самом конце (это то, что указано в сообщении об ошибке!)

Фактическая проблема заключалась в том, что массовая вставка не могла распознать EOF .. Мне пришлось изменить файл формата следующим образом, чтобы исправить это.. Тогда это сработало.

 11.0
29
1   SQLCHAR     0   8   ""      1   AccountId       ""
2   SQLCHAR     0   10  ""      2   TranDate        ""
3   SQLCHAR     0   4   ""      3   TransCode       ""
4   SQLCHAR     0   2   ""      4   AdditionalCode  ""
5   SQLCHAR     0   11  ""      5   CurrentPrincipa ""
6   SQLCHAR     0   11  ""      6   CurrentInterest ""
7   SQLCHAR     0   11  ""      7   LateInterest    ""
...
27  SQLCHAR     0   8   ""      27  Operator        ""
28  SQLCHAR     0   10  ""      28  UpdateDate      ""
29  SQLCHAR     0   12  "rn"  29  TimeUpdated     ""