使用 COPY 将 csv 读入数据库,同时添加常量列

Use COPY to read a csv into database, while adding constant columns

我有一系列 CSV 文件,格式为:

"Alice","Bob","A",123.46,"4"
"Charlie","Dana","B",987.6543,"9"
...

我想制作这样的table:

id   file_id  mch    c1         c2      c3   c4        c5
---  -------  -----  ---------  ------  ---  --------  ---
1    462      FALSE  'Alice'    'Bob'   'A'  123.46    '4'
2    462      FALSE  'Charlie'  'Dana'  'B'  987.6543  '9'
...  462      FALSE  ...        ...     ...  ...       ...
...  ...      ...    ...        ...     ...  ...       ...

其中

目前我正在使用以下 SQL 命令来 bulk-insert 我的每个 CSV 文件:

COPY pos(c1,c2,c3,c4,c5) 
FROM 'C:/Users/.../filename.csv' 
WITH (FORMAT CSV, HEADER FALSE, ENCODING 'UTF8')

用于填充主键 ID。这会生成一个没有 file_idmch 列的 table。

但我无法弄清楚如何在同一条语句中正确填充其他两列(file_idmch),而不执行整个其他 UPDATE 语句。

假设这个 table 定义:

CREATE TABLE pos (
  id        serial PRIMARY KEY
, file_id   int
, mch       bool
, c1        text
, c2        text
, c3        text
, c4        numeric
, c5        text
);

The manual on COPY:

Table columns not specified in the COPY FROM column list will receive their default values.

您已经看到 id 的效果,其中分配了默认值。其余要处理的列:mchfile_id:

  • mch is always false, at time of insertion

永久地做到这一点:

ALTER TABLE pos ALTER mc SET DEFAULT false;

必要权限:您必须拥有 table 或成为超级用户才能使用 ALTER TABLE

  • file_id is constant per file that I want to insert to this table, though varies between files. It is known before I try to bulk-add the file.

在运行宁COPY之前设置列默认值。如果您不希望其他插入具有相同的默认值,则可以在事务内执行此操作。 (DDL 命令在 Postgres 中是完全事务性的。)但这会为事务的其余部分锁定 table (ACCESS EXCLUSIVE lock)。

或者您在 COPY 之前 运行 一个单独的命令(在它自己的事务中)。那么默认值可能对并发事务有效。但是您只需要对 table.

进行非常简短的锁定
-- BEGIN;  -- optional transaction wrapper
ALTER TABLE pos ALTER file_id SET DEFAULT 462;

COPY pos(c1,c2,c3,c4,c5) 
FROM 'C:/Users/.../filename.csv' 
WITH (FORMAT CSV, HEADER FALSE, ENCODING 'UTF8');  -- unchanged!

-- ALTER TABLE pos ALTER file_id DROP DEFAULT;  -- optional
-- COMMIT;  -- if you BEGIN; also COMMIT;

您可能想要也可能不想在 COPY 之后重置 file_id 的列默认值。如果您要 运行 下一个 COPY 之后立即使用新的默认值,您可能只需设置新的默认值 ...

或者您可能想要记录旧的列默认值并重置它。参见:

  • Get the default values of table columns in Postgres?