Skip to content

Импорт CSV в SQL Server не должен быть таким сложным

Пересказ статьи Steve Jones. Importing a CSV into SQL Server Shouldn't Be This Hard


Как и многим из вас, недавно мне потребовалось импортировать некоторые данные в формате CSV (файл с разделителями-запятыми) в SQL Server. Это не был новый процесс, или приложение, которое требовало улучшения, и даже не необходимость в построении процесса ETL (извлечь, преобразовать, загрузить). Это был отдельный полуразовый запрос. С запросами подобного типа из разных источников я сталкивался годами. Администратор ли вы баз данных или разработчик, получив некие данные, вам хочется, чтобы они были очищены и представлены в структурированном формате, чтобы можно было легко создать отчет или проанализировать информацию.

В данном случае жена попросила помочь ей с налогами. Она экспортировала данные из различных банков и бухгалтерских систем и хотела получить отчеты с консолидированными данными.

Я заблуждался.

В этой статье рассматриваются некоторые неприятности и разочарования в работе с CSV в SQL Server, некоторые их которых, как я считаю, не вполне обязательны.

Беспорядочных данные


Как и некоторые из вас, я не люблю получать данные CSV со стороны. Если эти данные формирую я, то все прекрасно. Обычно я экспортирую данные таким образом, чтобы их легко было импортировать. Когда я получаю чужой CSV, обычно это не доставляет мне удовольствия. В данном случае жена прислала мне 2 zip файла с данными. Один был от Venmo, а другой - от Paypal. Архив Venmo содержал 12 файлов, по одному на каждый месяц. Каждый любовно именовался типа venmo_statement (1).csv, venmo_statement (2).csv и т.д. Архив Paypal содержал PDF на каждый месяц и один csv за весь год. По крайней мере, я буду проклинать Paypal только один раз во время всего процесса.

Часто первым шагом является просмотр данных. Содержимое Venmo представляло собой множество полей со строкой заголовка, содержащего начальный баланс, и последней строкой, содержащей конечный баланс. Имелось также несколько прекрасных разделов в середине с интересными символами. Вот пример поля внутри CSV.



Очевидно, я не буду импортировать такое в поля varchar().

Когда я открыл это в Sublime Text, чтобы получить представление о структуре, то увидел следующее:

Username,ID,Datetime,Type,Status,Note,From,To,Amount (total),Amount (fee),Funding Source,Destination,Beginning Balance,Ending Balance,Statement Period Venmo Fees,Terminal Location,Year to Date Venmo Fees,Disclaimer
HerdofTwo,,,,,,,,,,,,$500.00,,,,,
,5555555555555555,2020-01-10T02:50:47,Payment,Complete,Stock show,Cowboy Joe,My Wife,+ $10.00,,,Venmo balance,,,,Venmo,,
,555555555555555,2020-01-16T14:12:08,Payment,Complete,"You're magic ?? (sorry, totally spaced it)",Random Person,My Wife,+ $50.00,,,Venmo balance,,,,Venmo,,


Данные Paypal были проще и более структурированы, например:

"Date","Time","TimeZone","Name","Type","Status","Currency","Amount","Receipt ID","Balance"
"01/01/2020","19:04:43","PST","Sandra Dee","Mobile Payment","Completed","USD","500.00","","1,000.00"


Не так плохо, верно? Давайте начинать.

Настройка в SSMS


На первом шаге была создана база данных. Это легко. Затем я решил использовать мастер импорта плоского файла для загрузки моих данных. Это 12 файлов, и к тому времени, когда я действительно что-то запрограммирую, я могу легко пройти с мастером 12 раз.



Мастер простой, и он позволяет вам выбрать файл и создать таблицу. Я пройду это. После запуска мастера, я выбираю файл и даю имя таблице. Имя и схема предлагаются, но я могу их изменить.



Я не могу выбрать более одного файла, Это действительно мастер разового типа. Ну и хорошо. Я в состоянии сделать это 12 раз.

Затем я предварительно просматриваю данные. Я прокручиваю и не вижу ниже ничего, что бы было похоже на персональные данные. Однако вы можете видеть там предупреждение, что некоторые имена были изменены. Я подозреваю, что это имена столбцов, поскольку в CSV, вероятно, есть некоторые конфликты с ключевыми словами. Я мог бы использовать обнаружение расширенного типа данных, но не уверен, что будет лучше. Здесь всего 5 строк, поэтому экспериментировать особо не с чем.



Следующий шаг мастера - сопоставление типов данных для таблицы. Здесь я могу изменить типы, установить первичный ключ, допустимость NULL, и т.п. В моем случае nvarchar() нормально подходит для этих полей. Одна проблема с полем ID, который действительно должен быть строкового типа. На самом деле, я позже понял, что не позаботился о большинстве этих полей, но для начала мне нужно было загрузить их.



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



Это сработало, и я получил странную промежуточную таблицу. Однако всякий раз, когда я выполняю это, я получаю разные имена таблиц, что означает, что мне потребуются 12 операторов, чтобы собрать данные вместе. Это не конец света, но неудобно. Если я попытаюсь снова выполнить это, выбрав другой плоский файл и использовав то же самое имя таблицы, то получу такое сообщение:



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

И вообще, это был неплохой опыт, но он потребовал повторения импорта 12 файлов. Фактически 13, поскольку я должен еще получить оператор для загрузки PayPal.

Мастер импорта данных в SSMS


После моего первого импорта я подумал об использовании мастера импорта данных. Он достигается щелчком правой кнопкой на базе данных и выборе пункта контекстного меню Task (Задачи), как показано ниже.



Я думал, что это может стать лучшим вариантом, поскольку позволяет построить пакет SSIS, и может быть я смогу добавить туда цикл, и загрузить данные в одну таблицу. Я также думал, что было бы замечательно выполнять его ежемесячно по мере того, как моя жена будет получать новые файлы.

Работа мастера начинается с выбора источника данных. Я выбрал плоский файл, а затем мой файл. Первое недоумение посетило меня, когда я выбирал файл. Несмотря на сообщение "flat file source" (источник - плоский файл), по умолчанию в проводнике выбирались файлы .txt, что показано ниже.



Действительно плохой интерфейс. Я думал, что вариантами по умолчанию являются .txt, .csv и .tsv. Я знаю, что проводник может это делать, т.е. это просто ленивое программирование.

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



Затем я выбираю назначение. Я предпочитаю использовать драйвер OLEDB, главным образом из-за простых настроек строки подключения. Это работало в данном случае так же, как провайдер .NET.

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

Во-вторых, по умолчанию принимается авторизация SQL. Хотя все рекомендации, которые я видел от Microsoft, предлагали использовать авторизацию Windows, так почему бы не сделать её выбор по умолчанию? Далее, установлен флажок "Blank password" (пустой пароль), что нарушает, на мой взгляд, требования безопасности.



Возможно, последнее - здесь имеется множество настроек, которые я не часто изменяю. Думаю, что большинство людей также. Мы хотим ввести экземпляр и выбрать базу данных. Я должен перемещать мышку, изменять авторизацию и т.д. Разместите вначале то, что я использую изначально, и уберите все остальное на другие вкладки. В конце концов, разве в этом диалоговом окне нет вкладок?

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



Теперь я могу просмотреть резюме, сохранить пакет SSIS, и выполнить его. Однако я получаю вот что в результате простого импорта.



Хм, ошибка усечения. В этом файле только 5 строк, так почему мастер не смог подобрать правильный размер? Я вернулся и нашел это поле со значением по умолчанию varchar(50). Слишком мало, да и тип неверный, поэтому я меняю его на nvarchar(1050). Снова отказ. Тогда я меняю на 4000, что далеко превосходит то, что делал импорт плоских файлов (Flat File Import). Все равно не работает.

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

ADS


Azure Data Studio (ADS) имеет расширение для импорта в SQL Server, которое вы можете попробовать. Оно устанавливается из маркетплейса, и затем вы увидите это, когда щелкните на расширении.



Если вы прокрутите вниз, то увидите CTRL+I для запуска мастера. Первый раз у меня ушло 8-10с до появления диалога подключения, так что будьте терпеливы. Потом диалог открывается быстро. Также нет никакого значка этого подключения, которое отличало бы соединение с мастером импорта от обычного соединения с сервером, так что будьте осторожны.

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



Щелкаю Next, и перехожу к предварительному просмотру моих данных.



Затем я получил шанс проверить типы данных. Я пропустил это, т.к. было интересно, насколько хорошо это сработает, особенно учитывая небольшое число строк моих данных.



Затем мы получаем финальную страницу, и импорт начинается. У меня сразу выскочила ошибка. Теперь это было currency -> numeric (преобразование денег в число). Хотя я понимаю, что база данных не должна знать все символы денежных единиц, подумалось, что тут мастер мог бы оказаться поумнее. Если он распознал это как число, тогда он мог бы убрать разделители тысяч и символы валюты, особенно для моих текущих региональных настроек.



Я вернулся и поменял все числовые поля на nvarchar, и прошел до конца мастера. Теперь заработало.



Что мне понравилось в этом мастере, что там были не только кнопка "Done" или "OK", но также кнопка "Import new file" (импортировать новый файл). Это позволяет перезапустить мастера без лишних нажатий клавиш. Что и должно делать программное обеспечение. При этом мастер открывается с моими параметрами соединения и кнопкой "browse" (просматривать), позволяющей вернуться в последнему местоположению для выбора плоского файла.



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



Однако, в целом, мастер ADS оказался быстрее аналогичного в SSMS.

PowerShell


Посреди попыток заставить мастеров работать, я пожаловался в Twitter. Несколько человек предложили PowerShell, а другие заметили, что dba tools имеет команду Import-DbaCsv. Я решил попробовать. Моя первая попытка была самой простой. Я использовал эту команду:

Import-DbaCsv -Path "E:\Documents\Taxes\2020\Venmo statements\venmo_statement (6).csv" -SqlInstance Aristotle -Database HerdofTwo -Table "VenmoData"
Я получил ошибку, т.к. таблица не существовала.

Затем я добавил опцию -AutoCreateTable, и мой первый файл импортировался. Использовались столбцы nvarchar(max), но это было правильно. Я смог использовать быстрый цикл для импорта всех моих файлов. Это был простейший метод, т.к. существующая таблица не вызывала никаких проблем. Когда я импортировал первый файл, я убрал опцию и все последующие импортируемые файлы отправлялись в эту таблицу.

Я не попробовал команду Import-Csv, поскольку тогда мне нужно было бы самому проделать некоторые манипуляции, чтобы получить результаты в SQL Server.

Выводы


Мне нужно было импортировать несколько простых файлов для моей жены. В данном случае я имел 12 файлов в одном формате и 1 - в другом. Все что я хотел, это загрузить их в пару таблиц, а затем снова экспортировать. Я был удивлен, что инструменты SSMS были неуклюжи и громоздки в использовании. PowerShell, или более конкретно dba tools, оказалось наилучшим способом выполнить эту задачу, повторяемую 13 раз. После того, как я сделал это, у меня появился небольшой скрипт, который я могу использовать в будущем для импорта других файлов, если это потребуется.

Это была только часть моей работы, т.к. я должен был удалить некоторые строки (пункты начального/конечного баланса), а затем вытащить общие поля в таблицу, откуда я могу экспортировать их. Однако вместо предполагаемых 5 минут, задача превратилась в 20-30 минутное путешествие, главным образом, по причине изучения того, насколько плохо инструменты Microsoft обрабатывают простой файл csv. Я надеялся, что простой импорт в новую таблицу со всеми столбцами строкового типа окажется простым вариантом. Я также ожидал возможности повторения моего импорта в существующую таблицу.

Я знаю, что ETL - это сложная тема, и CSV могут быть довольно раздражающими, но в данном случае я думаю, что программное обеспечение построено и разработано не так хорошо, как могло бы быть.
Категории: T-SQL

Обратные ссылки

Нет обратных ссылок

Комментарии

Показывать комментарии Как список | Древовидной структурой

Нет комментариев.

Автор не разрешил комментировать эту запись

Добавить комментарий

Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.
Standard emoticons like :-) and ;-) are converted to images.

To prevent automated Bots from commentspamming, please enter the string you see in the image below in the appropriate input box. Your comment will only be submitted if the strings match. Please ensure that your browser supports and accepts cookies, or your comment cannot be verified correctly.
CAPTCHA

Form options

Добавленные комментарии должны будут пройти модерацию прежде, чем будут показаны.