Импорт CSV в PostgreSQL: частые ошибки новичков
CSV не загружается в PostgreSQL или данные попадают не в те столбцы? Разбираем типичные причины: разделитель, заголовок, кодировку, NULL и несовпадение типов — на примерах для PostgreSQL 16.

В PostgreSQL 16 импорт CSV чаще всего ломается не из-за сложных настроек, а из-за несовпадения файла и команды: в CSV точка с запятой вместо запятой, заголовок принимается за данные или пустая ячейка превращается не в то значение. Ниже — практические приёмы, которые помогут загрузить файл предсказуемо и найти ошибку до того, как она испортит рабочую таблицу.
Сначала проверьте файл и выберите способ загрузки
Для примеров понадобятся PostgreSQL 16, клиент psql, доступ к базе и тестовый CSV. Команда \copy запускается в psql и читает файл на компьютере, где работает клиент. SQL-команда COPY читает файл от имени сервера PostgreSQL: путь должен быть доступен серверу, а у пользователя должны быть необходимые права. Не подменяйте одну команду другой, если файл лежит на вашем ноутбуке.
Откройте CSV в текстовом редакторе, а не только в табличной программе. Посмотрите, чем разделены поля, есть ли первая строка с названиями столбцов, как записаны даты и пустые значения. Для надёжного импорта в рабочую таблицу сначала загрузите строки во временную или отдельную промежуточную таблицу.
Термин. Промежуточная таблица, или staging-таблица, — место для первичной загрузки данных, где их можно проверить и преобразовать до переноса в основные таблицы.
Три подхода и цена каждого
| Подход | Когда удобен | Чем приходится платить |
|---|---|---|
\copy в psql | Файл находится на компьютере пользователя | Нужно работать через psql; команда не является обычным SQL-запросом |
COPY | Файл доступен серверу, импорт запускается на серверной стороне | Нужны доступ к пути и соответствующие права; путь на ноутбуке серверу не виден |
| Импорт через GUI-клиент | Разовая загрузка и визуальная настройка колонок | Параметры нужно внимательно сверить; точные возможности зависят от клиента и его версии |
Для повторяемого локального импорта обычно удобна \copy. Для автоматизации на сервере чаще выбирают процесс, который сам контролирует доступ к файлам и повторный запуск. GUI не отменяет проверку результата: успешное уведомление не гарантирует, что столбцы сопоставились так, как вы ожидали.
Частые ошибки и как их разобрать
Неверный разделитель и заголовок
У CSV нет одного обязательного разделителя. Файл из русской локали может содержать точку с запятой, а команда по умолчанию ожидает запятые. Тогда PostgreSQL сообщит, например, о лишних данных после последнего ожидаемого столбца или не сможет разобрать строку. Укажите фактический разделитель через DELIMITER.
Если первая строка содержит названия полей, добавьте HEADER. Без него PostgreSQL попытается загрузить названия как обычную запись и может выдать ошибку преобразования типа. Само наличие заголовка не означает, что PostgreSQL сопоставит столбцы по именам: список колонок в команде задавайте явно и в нужном порядке.
Кавычки и запятые внутри поля
Запятая внутри значения должна быть оформлена по правилам CSV, обычно поле целиком заключают в двойные кавычки: "Москва, центр". Двойную кавычку внутри такого поля записывают как две кавычки подряд. Не пытайтесь исправить такие строки простым разбиением по запятой в редакторе: так вы разрушите границы полей.
Пустая строка — не всегда NULL
В CSV пустое поле и поле, содержащее пустую строку, могут иметь разный смысл. У параметров NULL и FORCE_NULL есть конкретное поведение для CSV; не меняйте их наугад. Сначала решите, что означает пустая ячейка в источнике, и проверьте это на нескольких строках. Иначе можно потерять различие между «значение неизвестно» и «значение намеренно пустое».
Кодировка и типы данных
Если вместо кириллицы появляются нечитаемые символы или загрузка завершается ошибкой кодировки, проверьте кодировку самого файла. Для UTF-8 укажите ENCODING 'UTF8'; не объявляйте файл UTF-8, если он сохранён в другой кодировке. Для дат проверьте фактический формат и настройки обработки даты в сессии: значения вроде 03/04/2025 неоднозначны без понимания порядка дня и месяца.
Не загружайте незнакомый файл сразу в таблицу с узкими типами и ограничениями. Число с десятичной запятой, пробел в числовом поле или дата в неожиданном формате остановят импорт. Сначала проверьте несколько строк, затем решите, нужно ли очищать и преобразовывать данные.
Импорт считается успешным не тогда, когда команда завершилась без ошибки, а когда число строк, значения и соответствие колонок совпадают с тем, что вы ожидали.
Безопасный шаблон: сначала отдельная таблица
Допустим, файл customers.csv содержит три столбца: id, email, created_at, а поля разделены запятыми и первая строка — заголовок. Создайте тестовую таблицу и загрузите данные из клиента. Команда \copy вводится в интерактивном psql; путь замените на расположение своего файла.
CREATE TEMP TABLE customers_import (
id text,
email text,
created_at text
);
\copy customers_import (id, email, created_at) FROM '/путь/к/customers.csv' WITH (FORMAT csv, HEADER true, DELIMITER ',', ENCODING 'UTF8');
SELECT count(*) FROM customers_import;
SELECT * FROM customers_import LIMIT 5;
Здесь поля временно объявлены текстовыми, чтобы сначала увидеть исходные значения. Это не универсальная схема: для большого файла и дальнейшей обработки выберите подходящие типы и структуру таблицы. Проверьте количество строк, первые записи и несколько записей ближе к концу файла. Если файл в UTF-8, а разделитель — точка с запятой, замените значение DELIMITER на ';'.
Если данные выглядят верно, переносите их в целевую таблицу отдельным шагом, явно перечисляя столбцы. До переноса проверьте дубликаты, обязательные поля и преобразование типов. Не запускайте повторный импорт вслепую: в зависимости от схемы он может добавить дубли или остановиться на ограничении уникальности.
Когда какой способ выбирать
- Файл у вас на компьютере, импорт разовый — начните с
\copyвpsql. - Файл лежит на сервере, а загрузка входит в серверный процесс — рассмотрите
COPY, предварительно проверив путь и права. - Нужно загрузить файл один раз и вы не пользуетесь
psql— подойдёт GUI-клиент, если в нём можно явно задать формат, разделитель, заголовок и сопоставление столбцов.
Для регулярного импорта важны повторяемость и контроль: фиксируйте формат файла, проверяйте количество записей и сохраняйте ошибочные строки для разбора. Если процесс должен безопасно переживать повторный запуск, отдельно продумайте ключи и правила обработки дублей.
Что делать, если не получилось
- Ошибка про лишние данные в строке. Сверьте число полей, разделитель и кавычки в указанной строке. Проверьте, не содержит ли значение незакрытую двойную кавычку.
- Ошибка преобразования типа. Найдите значение, которое не подходит столбцу: заголовок без
HEADER, текст в числовом поле или дата в неожиданном формате. Для диагностики загрузите данные в промежуточные текстовые столбцы. - Ошибка доступа к файлу. Для
\copyпроверьте путь и права пользователя, запустившегоpsql. ДляCOPYпроверьте доступ со стороны сервера, а не вашего компьютера. - Нечитаемая кириллица или ошибка кодировки. Определите реальную кодировку файла и укажите её корректно; простое изменение параметра не перекодирует содержимое файла.
- Команда завершилась, но строки не те. Проверьте порядок перечисленных колонок и первые записи после загрузки. Заголовок CSV сам по себе не выполняет сопоставление по именам.
Что делать дальше
После тестовой загрузки сравните ожидаемое и фактическое число строк, проверьте уникальность ключей и значения в полях с датами и числами. Затем перенесите данные в рабочую таблицу в контролируемой транзакции и зафиксируйте параметры импорта рядом с описанием процесса. Если файл поставляет внешняя система, договоритесь о стабильных разделителе, кодировке, заголовках и формате дат: это дешевле, чем разбирать новый вариант CSV после очередного импорта.
Транскрибатор встреч: Запись созвона или диктофона — в текст с разделением по спикерам, протоколом и списком задач.
Спросить за 25 ₽Источники: PostgreSQL 16: COPY, PostgreSQL 16: psql
Частые вопросы
Почему PostgreSQL считает всю строку одним столбцом?
Нужно ли указывать HEADER, если в CSV есть названия столбцов?
Почему \copy видит файл, а COPY — нет?
Можно ли импортировать CSV сразу в рабочую таблицу?
Что делать, если импорт прошёл, но часть данных выглядит неправильно?
Подойдут ли примеры для другой версии PostgreSQL?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.