【问题标题】:Use COPY to read a csv into database, while adding constant columns使用 COPY 将 csv 读入数据库,同时添加常量列
【发布时间】:2020-02-28 19:57:40
【问题描述】:

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

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

我想制作一个这样的表格:

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  ...        ...     ...  ...       ...
...  ...      ...    ...        ...     ...  ...       ...

在哪里

  • id 是主键,是任意的,应该按照插入的顺序自动生成。它是这样指定的。
  • file_id 是我要插入到此表中的每个文件的常量,但在文件之间有所不同。在我尝试批量添加文件之前就知道了。
  • mch 在插入时始终为假
  • c1c5 是通用列标题,类型是预先知道的。

目前我正在使用以下 SQL 命令批量插入我的每个 CSV 文件:

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

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

但我不知道如何正确填充同一语句中的其他两列(file_idmch),而不执行其他完整的 UPDATE 语句。

【问题讨论】:

  • 请记住始终提供您的表定义和 Postgres 版本。

标签: sql postgresql csv postgresql-copy


【解决方案1】:

假设这个表定义:

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:

COPY FROM 列列表中未指定的表列将接收其默认值。

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

  • mch 在插入时始终为假

做到这一点,永久:

ALTER TABLE pos ALTER mc SET DEFAULT false;

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

  • file_id 是我要插入此表的每个文件的常量,尽管文件之间有所不同。在我尝试批量添加文件之前就知道了。

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

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

-- 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,您可以设置新的默认值 ...

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多