复制列顺序

COPY column order

我正在尝试将 COPY 与 HEADER 选项一起使用,但我在文件中的 header 行的顺序与数据库中指定的列顺序不同。 我的文件中是否需要列名顺序??

我的代码如下:

COPY table_name (                                  
SELECT column_name
FROM information_schema.columns
WHERE table_schema = 'schema_name'
  AND table_name   = 'table_name'

            )                        
       FROM 'file.csv'  
       WITH DELIMITER ',' CSV HEADER;

我的数据库 table 的顺序与 file.csv 不同,我想 select table 顺序并将数据从 csv 复制到 table .

您不能在 copy from 中发出 SQL 查询。您只能列出列。

如果 CSV 列按 b, a, c 顺序排列,则在 copy from 命令中列出:

copy target_table (b, a, c)
from file.csv
with (delimiter ',', format csv, header)

假设我们需要的列的顺序是我们从中复制结果的 table 之一,下一个合乎逻辑的步骤是通过 Bash 模拟子查询脚本。

psql schema_origin -c 'COPY table_origin TO stdout' | \
psql schema_destination -c \
"$(echo 'COPY table_destination (' \
$(psql schema_origin -t -c "select string_agg(column_name, ',') \
from information_schema.columns where table_name = 'table_origin'") \
') FROM stdin')"


StackExchange answer on fetching column names
Whosebug answer on fetching results as tuples

我想出了以下设置来使 COPY TO/FROM 即使对于非常复杂的 JSON 列也能成功:

COPY "your_schema_name.yor_table_name" (
    SELECT string_agg(
        quote_ident(column_name), 
        ','
    ) FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE TABLE_NAME = 'yuour_table_name' 
    AND TABLE_SCHEMA = 'your_schema_name'
) FROM STDIN WITH CSV DELIMITER E'\t' QUOTE '\b' ESCAPE '\';
--here rows data
\.

最重要的部分:

  • 明确过滤 information_schema.columns 和用户 table_schema。否则,当一个 table 名称出现在多个模式中时,您可能会得到意外的列。
  • 使用 quote_ident 确保如果有人使用 userunique 等 Postgres 注册关键字对 table 列进行错误命名,您的命令不会崩溃。感谢 quote_ident,您可以将它们用双引号括起来,这使它们可以安全导入。
  • 我还发现了以下设置:

    • QUOTE '\b' - 用退格键引用
    • DELIMITER E'\t' - 制表符分隔符
    • ESCAPE '\' - 并用反斜杠转义

    用于使 COPY 来回最可靠也用于处理 sophisticated/nested JSON 列。