← Все курсы · Курс SQL

Загрузка вашего первого CSV в базу данных без повреждения данных

Майкл Носито · Обновлено в августе 2026 г. · Все числа на этой странице были обработаны до их публикации.

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

Что вы делаете: создаете таблицу сами, загружаете все как текст, проверяете, затем приводите в чистую таблицу. Это один дополнительный шаг, и он делает всю нагрузку обратимой.

Краткая версия. Позвольте импортеру перенести данные. Не позволяйте ему решать типы.

Пять решений перед загрузкой

РешениеНеправильный ответ будет стоить вам
Какие столбцы являются текстовыми, а не цифровымиВедущие нули и идентификаторы длиной более 15 цифр.
Какой столбец является ключевымПозже вы узнаете, что это не уникально.
Какой формат даты использует файлТреть строк молча ошибается
В какой кодировке он находитсяИмена, поступающие как é и £
Есть ли в файле ненужные строкиОбщая строка становится записью

Ответьте на все пять, просмотрев файл, прежде чем прикасаться к базе данных. Откройте первую тысячу строк в текстовом редакторе, а не в Excel, потому что к моменту просмотра Excel уже изменит некоторые из них. Эта команда просмотра находится в открытие большого CSV.

Постановочный шаблон

Два стола. Один хранит все в виде текста в том виде, в каком оно поступило; другой содержит напечатанную, очищенную версию. Это звучит как дополнительная работа и занимает около четырех минут.

-- 1. staging: every column TEXT, nothing can be lost
CREATE TABLE orders_raw (
  order_id   TEXT,
  customer   TEXT,
  order_date TEXT,
  amount     TEXT,
  status     TEXT
);

-- 2. import into it (sqlite3 shell)
.mode csv
.import --skip 1 orders.csv orders_raw

-- 3. look before casting
SELECT COUNT(*) FROM orders_raw;
SELECT * FROM orders_raw LIMIT 10;
SELECT order_date FROM orders_raw
WHERE order_date NOT LIKE '____-__-__' LIMIT 20;

Именно этот третий запрос и определяет шаблон. В нем перечислены значения, которые не имеют ожидаемой формы, прежде чем какое-либо преобразование их выбросит.

-- 4. cast into the real table, deliberately
CREATE TABLE orders (
  order_id   TEXT PRIMARY KEY,
  customer   TEXT,
  order_date DATE,
  amount     REAL,
  status     TEXT
);

INSERT INTO orders
SELECT TRIM(order_id),
       TRIM(customer),
       DATE(order_date),
       CAST(REPLACE(REPLACE(amount, ',', ''), '£', '') AS REAL),
       LOWER(TRIM(status))
FROM orders_raw
WHERE order_id IS NOT NULL AND order_id <> '';

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

Сохраните идентификатор заказа как ТЕКСТ. Даже если оно выглядит числовым. Идентификаторы — это скорее метки, чем количества: вы никогда не добавляете два из них, иногда вам нужны ведущие нули, и все, что превышает 15 цифр, теряет точность как число. Тот же аргумент применяется в Excel, в ведущие нули при импорте.

Три проверки после загрузки

-- 1. row count against the file
SELECT COUNT(*) FROM orders;          -- compare with wc -l, minus the header

-- 2. no column silently empty
SELECT SUM(CASE WHEN order_date IS NULL THEN 1 ELSE 0 END) AS null_dates,
       SUM(CASE WHEN amount     IS NULL THEN 1 ELSE 0 END) AS null_amounts
FROM orders;

-- 3. a value you can verify by eye
SELECT * FROM orders WHERE order_id = '00042';

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

Другие инструменты

инструментКоманда
SQLite-оболочка.mode csv затем .import --skip 1 file.csv table
Браузер БД для SQLiteФайл, Импорт, Таблица из файла CSV
DuckDBCREATE TABLE t AS SELECT * FROM read_csv_auto('file.csv')
PostgreSQL\copy orders FROM 'file.csv' CSV HEADER
pandasdf.to_sql('orders', con, if_exists='append', index=False)

DuckDB's read_csv_auto необычайно хорош в догадках, и вы можете переопределить любой столбец с помощью types аргумент, когда догадка неверна. Постгрес \copy запускает клиентскую сторону, что важно, потому что простой COPY команде необходимо, чтобы файл находился на сервере.

Когда файл будет приходить каждый месяц

  1. Пишите нагрузку как скрипт, а не как последовательность кликов.
  2. Поместите имя исходного файла и дату загрузки в столбец, чтобы можно было отследить любую строку.
  3. Загрузите в промежуточную версию, запустите проверки и только потом замените или добавьте в чистую таблицу.
  4. Сохраните необработанные файлы. Хранилище стоит дешево, и единственным реальным восстановлением является перезагрузка.
  5. Запишите количество строк каждой загрузки в небольшую таблицу. Дрифт проявляется как число, а не как ощущение.

Как применить это в своей работе

  1. Создайте таблицу самостоятельно для следующего загружаемого файла, а не позволяйте этому инструменту сделать это.
  2. Добавьте промежуточный шаг один раз и посмотрите, сколько он зафиксирует в файле, который, по вашему мнению, был чистым.
  3. Запустите три проверки и запишите цифры в примечаниях к проекту.
  4. Создайте текст каждого столбца идентификатора и затем проверьте один известный идентификатор.
  5. Превратите повторный импорт в сценарий, если вы делаете это впервые дважды.

Единственная привычка, которую нужно сохранить

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

Знаете ли вы количество строк в последнем файле, который вы во что-нибудь загрузили?

Написано с помощью инструментов по мере их доставки. Все команды SQLite точка, DuckDB read_csv_auto, копирование на стороне клиента Постгрес и pandas to_sql являются текущими.
Успешный импорт — это не то же самое, что правильный импорт.

SQL для аналитиков — это 458 страниц, которые считывают запросы построчно в повседневных словах, поэтому ошибочный результат нужно где-то отслеживать, а не перепечатывать, пока он не станет выглядеть лучше.

SQL для аналитиков, 19 $ →
На этапе загрузки возникает большинство проблем с данными.

Настройка базы данных SQL покрывает инструмент, проверка качества данных о том, что нужно запустить потом, и Настройка базы данных крышки, какой из них установить.

Прочтите проверки качества данных →