Импорт CSV в PostgreSQL: пошаговая инструкция
Показываем безопасный импорт CSV в PostgreSQL 16 через psql: от проверки заголовков и создания таблицы до загрузки, диагностики ошибок кодировки, разделителей и лишних колонок.

За 10–20 минут вы загрузите локальный CSV-файл в PostgreSQL 16 через утилиту psql, проверите число строк и убедитесь, что значения попали в правильные столбцы. Инструкция рассчитана на импорт файла с компьютера, где запущен psql; для файла на сервере команда будет другой.
Что нужно иметь до начала
- PostgreSQL 16 и доступ к базе данных.
- Установленный клиент
psqlверсии 16 или совместимой версии. - Имя базы, адрес сервера, порт, имя пользователя и пароль.
- CSV-файл в кодировке UTF-8. В примерах он называется
customers.csv. - Права на создание таблицы и загрузку данных в неё.
Проверьте версию клиента до начала:
psql --version
В ответе должна быть строка с версией 16.x или другой версией, которую вы используете осознанно. Синтаксис \copy, показанный ниже, поддерживается в современных версиях PostgreSQL, но названия параметров и поведение лучше сверять с документацией вашей версии.
Главная развилка при импорте —
COPYчитает файл со стороны сервера, а\copy— со стороны клиентаpsql. Для локального CSV почти всегда нужна именно\copy.
CSV — текстовый формат, где строки разделены переводами строк, а поля внутри строки — выбранным разделителем, чаще всего запятой или точкой с запятой.
Шаг 1. Проверьте CSV до подключения к базе
Откройте файл в редакторе, который показывает кодировку и разделитель. Для этой инструкции допустим такой файл с заголовком:
email,name,registered_at
anna@example.com,Анна,2024-05-10
boris@example.com,Борис,2024-05-11
Убедитесь в четырёх вещах:
- в первой строке ровно три столбца:
email,name,registered_at; - разделитель — запятая, а не точка с запятой;
- даты записаны в формате
YYYY-MM-DD; - текст с запятыми заключён в двойные кавычки, например
"Москва, центр".
Проверка пройдена, если количество значений в каждой строке совпадает с количеством заголовков, а русские буквы отображаются нормально.
Шаг 2. Подключитесь к PostgreSQL
Откройте терминал и выполните команду, подставив свои значения:
psql -h localhost -p 5432 -U app_user -d shop
Введите пароль, когда psql его запросит. Пароль не добавляйте в команду и не сохраняйте в истории оболочки. После подключения должна появиться строка приглашения вида shop=>.
Если база работает на том же компьютере с настройками по умолчанию, параметры -h и -p иногда можно не указывать. Для удалённой базы оставьте их явно: так проще заметить подключение не к тому серверу.
Шаг 3. Создайте таблицу под структуру файла
Выполните SQL в открытой сессии psql:
CREATE TABLE customers (
email text NOT NULL,
name text NOT NULL,
registered_at date NOT NULL
);
Проверка: PostgreSQL ответит CREATE TABLE. Названия и типы столбцов должны соответствовать данным, а не только заголовкам CSV. Например, дату можно загрузить в date, но значение с временем потребует другого типа.
Если таблица уже существует, этот шаг пропустите и проверьте её структуру:
\d customers
В выводе должны быть перечислены столбцы email, name и registered_at с ожидаемыми типами.
Шаг 4. Загрузите локальный CSV через \copy
Находясь в той же сессии psql, выполните:
\copy customers (email, name, registered_at)
FROM '/полный/путь/customers.csv'
WITH (FORMAT csv, HEADER true, ENCODING 'UTF8');
В Windows укажите путь с прямыми слешами, например C:/data/customers.csv. В Linux и macOS используйте существующий абсолютный путь, например /home/user/data/customers.csv. Параметр HEADER true пропускает первую строку с названиями столбцов.
Проверка: команда завершится сообщением вроде COPY 2. Число означает количество загруженных строк. Если файл разделён точкой с запятой, добавьте параметр DELIMITER ';':
\copy customers (email, name, registered_at)
FROM 'C:/data/customers.csv'
WITH (FORMAT csv, HEADER true, DELIMITER ';', ENCODING 'UTF8');
Не указывайте одновременно запятую и точку с запятой: PostgreSQL не угадывает структуру файла по расширению.
Шаг 5. Проверьте результат запросами
Сначала посчитайте строки:
SELECT count(*) FROM customers;
Результат должен совпадать с числом строк данных в CSV без заголовка. Затем проверьте несколько записей:
SELECT email, name, registered_at
FROM customers
ORDER BY registered_at, email
LIMIT 10;
Проверка завершена, если количество строк ожидаемое, имена отображаются без кракозябр, а даты распознаны как даты. Для повторного импорта не запускайте команду вслепую: она добавит строки ещё раз.
Если не получилось
«No such file or directory»
\copy не нашла файл на компьютере, где запущен psql. Проверьте абсолютный путь, регистр букв и расширение файла. На Windows проверьте, что это не скрытый файл с именем customers.csv.csv.
«Permission denied»
Операционная система запрещает читать файл текущему пользователю. Переместите CSV в каталог, к которому у него есть доступ, либо измените права. Это не обязательно ошибка прав пользователя PostgreSQL: при \copy файл читает клиентская программа.
«extra data after last expected column»
В строке больше значений, чем указано в списке столбцов. Чаще всего причина — неправильный разделитель или запятая внутри текста без двойных кавычек. Откройте проблемную строку и сравните её с заголовком.
«invalid input syntax for type date»
Значение нельзя преобразовать в тип date. Исправьте формат даты в CSV или выберите тип столбца, соответствующий реальным данным. Не меняйте тип на text только ради обхода ошибки: так вы потеряете проверку корректности дат.
«invalid byte sequence for encoding UTF8»
Файл сохранён не в UTF-8 либо содержит смешанную кодировку. Пересохраните его как UTF-8 без BOM в редакторе, который явно показывает кодировку, и повторите импорт. Если файл гарантированно в другой кодировке, параметр ENCODING нужно заменить на её название из документации PostgreSQL.
Чем отличается COPY от \copy
SQL-команда COPY и метакоманда \copy выглядят похоже, но читают файл в разных местах. Это критично для удалённого сервера.
| Команда | Где находится CSV | Когда выбирать |
|---|---|---|
\copy | На компьютере, где запущен psql | Локальный файл, удалённая база или нет прав на каталог сервера |
COPY | На сервере PostgreSQL | Файл уже размещён на сервере, и у роли есть нужные права |
Для COPY сервер должен иметь доступ к указанному пути, а роль — право на чтение файла на стороне PostgreSQL. Поэтому попытка заменить \copy на COPY часто заканчивается ошибкой доступа или сообщением о том, что файла нет.
Где этот способ ломается
Пошаговый импорт подходит для небольшого или разового CSV. На больших файлах проблема обычно не в синтаксисе, а в отсутствии контроля над повторным запуском и частично загруженными данными.
- Если в таблице есть уникальное ограничение, повторная загрузка может завершиться ошибкой на дубликате.
- Если CSV содержит тысячи строк с разными форматами дат и чисел, сначала загрузите его во временную staging-таблицу с текстовыми столбцами, а затем преобразуйте данные отдельным запросом.
- Если импорт прервался, проверьте, сколько строк уже записано, прежде чем запускать его снова.
- Если файл создаёт сторонняя система, зафиксируйте её разделитель, кодировку, правила кавычек и обозначение пустых значений.
Транзакции, промежуточные таблицы и дедупликация — отдельная тема; здесь рассматривается базовый импорт корректного файла.
Что делать дальше
После первого успешного импорта сохраните команду с путём к файлу в рабочей инструкции проекта, но без пароля. Затем добавьте проверку количества строк и несколько контрольных запросов. Для регулярной загрузки измеряйте длительность импорта, число отклонённых строк и количество дубликатов, а схему таблицы защищайте ограничениями NOT NULL, UNIQUE и внешними ключами там, где они действительно отражают правила данных.
Антиблок-аналитик 115-ФЗ: Анализ выписок, поиск рисков блокировки счёта, инструкции по безопасным транзакциям.
Спросить за 41 ₽Источники: PostgreSQL 16: COPY, PostgreSQL 16: psql
Частые вопросы
Можно ли импортировать CSV без установки PostgreSQL на своём компьютере?
Почему PostgreSQL не видит файл, хотя он есть на компьютере?
Что делать, если CSV разделён точкой с запятой?
Как не загрузить одни и те же строки дважды?
Можно ли загрузить CSV в уже существующую таблицу?
Что делать с пустыми значениями в CSV?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.