Я бы COPY
файл во временную таблицу и обновил фактическую таблицу оттуда.Может выглядеть так:
CREATE TEMP TABLE tmp_x (id int, apple text, banana text); -- but see below
COPY tmp_x FROM '/absolute/path/to/file' (FORMAT csv);
UPDATE tbl
SET banana = tmp_x.banana
FROM tmp_x
WHERE tbl.id = tmp_x.id;
DROP TABLE tmp_x; -- else it is dropped at end of session automatically
Если импортируемая таблица соответствует таблице, которая должна быть точно обновлена, это может быть удобно:
CREATE TEMP TABLE tmp_x AS SELECT * FROM tbl LIMIT 0;
Создает пустую временную таблицу, соответствующую структуресуществующая таблица, без ограничений.
Привилегии
SQL COPY
для этого требуются привилегии суперпользователя.( Руководство ):
COPY
присвоение имени файлу или команде разрешено только суперпользователям базы данных, поскольку позволяет читать или записывать любой файл, к которому у сервера есть права доступа..
Метакоманда psql \copy
работает для любой роли БД. Руководство:
Выполняет копию клиентского приложения.Эта операция запускает команду SQL COPY , но вместо чтения или записи указанного файла сервером psql читает или записывает файл и направляет данные между сервером и локальной файловой системой.Это означает, что доступность файлов и привилегии принадлежат локальному пользователю, а не серверу, и привилегии суперпользователя SQL не требуются.
Область действия временных таблиц ограничена одним сеансом одной роли, так что вышеупомянутое должно быть выполнено в том же сеансе psql:
CREATE TEMP TABLE ...;
\copy tmp_x FROM '/absolute/path/to/file' (FORMAT csv);
UPDATE ...;
Если вы пишете это в команде bash, обязательно оберните все это в один PSQL вызов.Например:
echo 'CREATE TEMP TABLE tmp_x ...; \copy tmp_x FROM ...; UPDATE ...;' | psql
Обычно вам нужна мета-команда \\
для переключения между мета-командами psql и SQL-командами в psql, но \copy
является исключением из этого правила.Руководство снова:
специальные правила синтаксического анализа применяются к мета-команде \copy
.В отличие от большинства других мета-команд, весь остаток строки всегда принимается за аргументы \copy
, и в аргументах не выполняется ни интерполяция переменных, ни расширение обратных кавычек.
Большие таблицы
Если таблица импорта велика, то может быть временно увеличено temp_buffers
для сеанса (первое в сеансе):
SET temp_buffers = '500MB'; -- example value
Добавить индекс во временную таблицу:
CREATE INDEX tmp_x_id_idx ON tmp_x(id);
И запустить ANALYZE
вручную, так как временные таблицы не охватываются автоочисткой / автоанализом.
ANALYZE tmp_x;
Связанные ответы: