BULK INSERT/OPENROWSET FormatFile Terminator для CSV файла с (запятой) в данных

63
4

Я написал хороший импорт для моей миллионной CSV-таблицы, которая работает очень хорошо (с использованием OPENROWSET BULK (я не использовал BULK INSERT, потому что мне нужно перекреститься с некоторыми другими столбцами). Формат файла использует запятую как Terminator.

Вот пример CSV, который я использовал для разработки:

Reference, Name, Street
1,Dave Smith, 1 Test Street
2,Sally SMith,1 Test Street

Как только я заработал, кто-то напомнил мне, что у самих данных может быть запятая, кричит !!!!

Reference, Name, Street
"1","Dave Smith", "1 Test Street"
"2","Sally Smith","1,Test Street" <-comma in street

Как люди имеют дело с CSV с запятой в данных с помощью FormatFiles? (Или я просто говорю, что файл должен быть ограничен TAB)?

спросил(а) 2021-01-25T20:33:03+03:00 4 месяца, 4 недели назад
1
Решение
78

Если в данных может быть полевой терминатор, тогда лучше всего использовать разделитель TAB или PIPE (или что-то, что работает для ваших данных).

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

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

ответил(а) 2021-01-25T20:33:03+03:00 4 месяца, 4 недели назад
45

Разделители в полях данных - общая проблема с файлами с разделителями. Некоторые общие тактики для решения этой проблемы включают:

Воссоздайте файл данных со всеми вхождениями разделителя, удаленных из полей данных, прежде чем они будут записаны в файл: это устраняет ошибки OPENROWSET, но не сохраняет целостность данных. Повторно создайте файл данных с другим символом разделителя: по моему опыту лучше всего выбрать разделитель табуляции. Менее часто встречается символ табуляции, чем запятая в данных. Но это, конечно, не неслыханно. Я также видел вкладки в данных. Примените поля данных в двойных кавычках: для этого требуются некоторые настройки файла формата XML.

Ручное редактирование файла данных может быть выполнено для любого из указанных выше параметров. Но это может быть утомительно, особенно для больших файлов. (Просто открыть файл из нескольких GB в Notepad.exe - это упражнение в терпении.) Реально, вы бы хотели, чтобы автор заново создал его для вас. Вариант №1 должен всегда "работать". Но опять же, проблема с целостностью данных, с которой вы, возможно, не сможете жить. Вариант № 2, вероятно, будет работать для многих случаев, но он не пуленепробиваемый. Вариант № 3 также не является пуленепробиваемым (всегда возможно иметь разделитель в поле данных), но он примерно так же близок, насколько вы можете получить. Кроме того, он сохраняет целостность данных.

Вот одна возможность для файла формата XML:

<?xml version="1.0"?>
<BCPFORMAT xmlns="http://schemas.microsoft.com/sqlserver/2004/bulkload/format" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<RECORD>
<FIELD ID="1" xsi:type="CharTerm" TERMINATOR='","' MAX_LENGTH="5"/>
<FIELD ID="2" xsi:type="CharTerm" TERMINATOR='","' MAX_LENGTH="128" COLLATION="SQL_Latin1_General_CP1_CI_AS"/>
<FIELD ID="3" xsi:type="CharTerm" TERMINATOR='"\r\n' MAX_LENGTH="128" COLLATION="SQL_Latin1_General_CP1_CI_AS"/>
</RECORD>
<ROW>
<COLUMN SOURCE="1" NAME="Reference" xsi:type="SQLVARYCHAR"/>
<COLUMN SOURCE="2" NAME="Name" xsi:type="SQLVARYCHAR"/>
<COLUMN SOURCE="3" NAME="Street" xsi:type="SQLVARYCHAR"/>
</ROW>
</BCPFORMAT>

Обратите внимание на FIELD TERMINATOR: я использовал одинарные кавычки, чтобы идентифицировать "," в качестве терминатора и "\r\n в качестве терминатора строк (терминатор COLUMN 3). Я сделал обоснованное предположение, что Name и Street имеют до 128 символов - отредактируйте это при необходимости.

Проблемы:

OPENROWSET() запросы будут возвращать Reference с ведущим " двойной кавычки. И из - за этого... Reference не может быть возвращена как INT (или SMALLINT, BIGINT и т.д.). Он возвращается как VARCHAR (xsi:type="SQLVARYCHAR")

Для конкретного предоставленного примера данных я бы удалил двойные кавычки из полей " Reference данные", отредактировал файл формата XML, чтобы FIELD ID="1" имел TERMINATOR=',"' и далее корректировал файл формата XML, чтобы COLUMN SOURCE="1" имеет xsi:type="SQLINT".

Для получения дополнительной информации это сообщение в блоге может помочь: Начало работы с OPENROWSET и поставщиком BULK Rowset - часть 2

ответил(а) 2021-01-25T20:33:03+03:00 4 месяца, 4 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема