如何使用Postgres中的CSV文件中的值更新选定的行?

use*_*753 64 sql database csv postgresql file-io

我正在使用Postgres,并希望进行一个从CSV文件中获取的大更新查询,假设我得到了一张表(id, banana, apple).

我想运行一个更新香蕉而不是苹果的更新,每个新香蕉及其ID都将在CSV文件中.

我试着查看Postgres网站,但是这些例子正在扼杀我.

Erw*_*ter 135

我将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
Run Code Online (Sandbox Code Playgroud)

如果导入的表与要更新的表匹配,则可能很方便:

CREATE TEMP TABLE tmp_x AS SELECT * FROM tbl LIMIT 0;
Run Code Online (Sandbox Code Playgroud)

创建一个与现有表的结构匹配的空临时表,没有约束.

特权

SQL COPY需要超级用户权限.(手册):

COPY 命名文件或命令仅允许数据库超级用户,因为它允许读取或写入服务器有权访问的任何文件.

psql的元命令\copy适用于任何数据库的作用.手册:

执行前端(客户端)副本.这是一个运行SQL COPY命令的操作,但不是服务器读取或写入指定的文件,psql读取或写入文件并在服务器和本地文件系统之间路由数据.这意味着文件可访问性和权限是本地用户的权限,而不是服务器的权限,并且不需要SQL超级用户权限.

临时表的范围仅限于单个角色的单个会话,因此必须在同一个psql会话中执行以上操作:

CREATE TEMP TABLE ...;
\copy tmp_x FROM '/absolute/path/to/file' (FORMAT csv);
UPDATE ...;
Run Code Online (Sandbox Code Playgroud)

如果您使用bash命令编写脚本,请确保将其全部包含在单个 psql调用中.喜欢:

echo 'CREATE TEMP TABLE tmp_x ...; \copy tmp_x FROM ...; UPDATE ...;' | psql
Run Code Online (Sandbox Code Playgroud)

通常,您需要meta-command COPY在psql中切换psql元命令和SQL命令,但这\\是此规则的一个例外.手册再次:

特殊解析规则适用于\copy元命令.与大多数其他元命令不同,该行的整个剩余部分始终被视为参数\copy,并且在参数中既不执行变量插值也不执行反引号扩展.

大桌子

如果import-table很大\copy,那么会话可能会暂时增加(会话中的第一件事):

SET temp_buffers = '500MB';  -- example value
Run Code Online (Sandbox Code Playgroud)

向临时表添加索引:

CREATE INDEX tmp_x_id_idx ON tmp_x(id);
Run Code Online (Sandbox Code Playgroud)

并且temp_buffers手动运行,因为临时表不包含在autovacuum/auto-analyze中.

ANALYZE tmp_x;
Run Code Online (Sandbox Code Playgroud)

相关答案:

  • `COPY tmp_x FROM'/ absolute/path/to/file'(DELIMITER';',HEADER TRUE,FORMAT CSV)`对我来说效果更好.见(http://www.postgresql.org/docs/9.1/static/sql-copy.html) (3认同)