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;
创建一个与现有表结构匹配的空临时表,没有约束。
特权
在 Postgres 10 之前,SQL COPY 需要超级用户权限。
在 Postgres 11 或更高版本中,还有一些 predefined roles(以前的“默认角色”)允许它。 The manual:
COPY 命名文件或命令只允许数据库超级用户使用
或被授予角色pg_read_server_files 之一的用户,
pg_write_server_files,或pg_execute_server_program [...]
psql 元命令\copy 适用于任何数据库角色。 The manual:
执行前端(客户端)复制。这是一个运行
SQL COPY 命令,而不是服务器读取或写入
指定文件,psql读取或写入文件并路由数据
服务器和本地文件系统之间。这意味着该文件
可访问性和权限是本地用户的,而不是
服务器,并且不需要 SQL 超级用户权限。
临时表的作用域仅限于单个角色的单个session,所以以上必须在同一个psql session中执行:
CREATE TEMP TABLE ...;
\copy tmp_x FROM '/absolute/path/to/file' (FORMAT csv);
UPDATE ...;
如果您在 bash 命令中编写脚本,请确保将其全部包装在 single psql 调用中。喜欢:
echo 'CREATE TEMP TABLE tmp_x ...; \copy tmp_x FROM ...; UPDATE ...;' | psql
通常,您需要元命令\\ 来在psql 元命令和psql 中的SQL 命令之间切换,但\copy 是此规则的一个例外。 The manual again:
特殊的解析规则适用于\copy 元命令。与大多数其他元命令不同,该行的整个剩余部分始终作为 \copy 的参数,并且在参数中既不执行变量插值也不执行反引号扩展。
大桌子
如果导入表很大,可能需要为会话临时增加temp_buffers(会话中的第一件事):
SET temp_buffers = '500MB'; -- example value
为临时表添加索引:
CREATE INDEX tmp_x_id_idx ON tmp_x(id);
并手动运行ANALYZE,因为自动清理/自动分析不涵盖临时表。
ANALYZE tmp_x;
相关答案: