Перейти к содержанию
Innovialabs

Как импортировать CSV и Excel в PostgreSQL

Практика3 мин

Коротко

Загружайте файл сначала во временную staging-таблицу с текстовыми колонками через COPY, \copy, DBeaver или Python, затем приводите типы, убирайте дубли и переносите проверенные данные в рабочую таблицу.

Короткий ответ

Надёжная схема импорта одна для любого инструмента:

  1. Загрузить файл как есть в staging-таблицу, где все колонки — text.
  2. Преобразовать типы, даты и форматы SQL-запросом.
  3. Перенести данные в рабочую таблицу, отсеяв дубли.
  4. Проверить результат: количество строк, пустые значения, суммы.

Так ошибка в одной строке файла не обрывает весь импорт, а плохие данные не попадают в рабочие таблицы.

Какой инструмент выбрать

СпособКогда подходит
COPYФайл уже лежит на сервере базы данных, нужны скорость и большие объёмы
\copy в psqlФайл на вашем компьютере, а база удалённая
DBeaverРазовая загрузка без командной строки, с визуальным сопоставлением колонок
Python (pandas)Excel с несколькими листами, сложная очистка, регулярный автоматический импорт

Подготовка staging-таблицы

CREATE TABLE staging_clients (
  name    text,
  phone   text,
  city    text,
  created text
);

Текстовые колонки принимают что угодно: «12.03.2026», «n/a», пробелы. Разбираться с этим удобнее уже в SQL.

COPY и \copy

COPY читает файл на сервере PostgreSQL. Для этого нужны права суперпользователя или роль pg_read_server_files.

COPY staging_clients (name, phone, city, created)
FROM '/var/lib/postgresql/import/clients.csv'
WITH (FORMAT csv, HEADER true, DELIMITER ';', ENCODING 'WIN1251');

\copy — команда клиента psql: файл читается на вашей машине и передаётся на сервер. Команда пишется в одну строку:

\copy staging_clients (name, phone, city, created) FROM 'clients.csv' WITH (FORMAT csv, HEADER true, DELIMITER ';', ENCODING 'WIN1251')

Ключевые параметры:

  • DELIMITER — Excel с русской или узбекской локалью часто сохраняет CSV с точкой с запятой, а не запятой.
  • ENCODING — старые выгрузки из Excel и 1С бывают в WIN1251. Если вместо кириллицы видите «кракозябры», проблема в кодировке. Лучше сразу сохранять как «CSV UTF-8».
  • HEADER — пропустить строку с заголовками.

DBeaver

Подходит, когда нужно загрузить файл один раз и без консоли:

  1. Правый клик по staging-таблице → Import Data → CSV.
  2. Укажите кодировку, разделитель и формат даты в настройках импорта.
  3. Проверьте сопоставление колонок файла и таблицы.
  4. Запустите импорт и посмотрите лог ошибок.

Файл Excel перед этим сохраните как CSV или используйте Python.

Python и Excel

Для Excel удобнее всего pandas: он читает листы .xlsx напрямую (нужен пакет openpyxl).

import pandas as pd
from sqlalchemy import create_engine

df = pd.read_excel("clients.xlsx", sheet_name="Клиенты", dtype=str)
df.columns = ["name", "phone", "city", "created"]

engine = create_engine("postgresql+psycopg://user:password@localhost:5432/shop")
df.to_sql("staging_clients", engine, if_exists="append", index=False, chunksize=1000)

dtype=str важен: без него Excel и pandas превращают телефоны в числа, теряют ведущие нули и показывают длинные номера в экспоненциальном виде. Пароль к базе храните в переменных окружения, а не в коде.

Даты, форматы и дубли

Преобразуйте и перенесите данные одним запросом:

INSERT INTO clients (name, phone, city, created_at)
SELECT DISTINCT ON (phone_clean)
       trim(name),
       phone_clean,
       nullif(trim(city), ''),
       to_date(created, 'DD.MM.YYYY')
FROM (
  SELECT *, regexp_replace(phone, '\D', '', 'g') AS phone_clean
  FROM staging_clients
) s
WHERE phone_clean <> ''
ORDER BY phone_clean
ON CONFLICT (phone) DO NOTHING;

Что здесь происходит:

  • to_date с явным форматом не даёт перепутать день и месяц;
  • телефоны приводятся к цифрам, чтобы «+998 90 123-45-67» и «998901234567» считались одним номером;
  • DISTINCT ON убирает дубли внутри файла, ON CONFLICT — пересечения с уже существующими данными (нужен уникальный индекс по phone).

Проверка после импорта

  • Сравните число строк в файле, staging и рабочей таблице. Разница должна объясняться дублями и отброшенными строками.
  • Посчитайте NULL в обязательных полях.
  • Сверьте суммы и диапазоны: даты не из будущего, суммы без отрицательных значений.
  • Посмотрите несколько случайных строк глазами.

После успешной проверки очистите staging через TRUNCATE.

Частые вопросы

COPY выполняется сервером и читает файл с диска сервера, поэтому требует особых прав. \copy выполняет psql на вашем компьютере и отправляет данные на сервер — это обычный выбор для удалённой базы.

Поможем с этим

Если хотите не разбираться самим, а получить результат — этим мы занимаемся каждый день.

Обсудить проект

Читайте также

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.