如何将 CSV 复制为 JSON 字段

How to COPY CSV as JSON fields

有没有办法将 CSV 文件数据直接复制到 JSON 或 JSONb 数组中?

示例:

CREATE TABLE mytable (
    id serial PRIMARY KEY,
    info jSONb -- or JSON
);
COPY mytable(info) FROM '/tmp/myfile.csv' HEADER csv;

注意:每个 CSV 行都映射到一个 JSON 数组。这是一个普通的 CSV。


普通 CSV(未嵌入 JSON).../tmp/myfile.csv =

a,b,c
100,Mum,Dad
200,Hello,Bye

正确的 COPY 命令必须等同于下面的普通复制。

普通 COPY(丑陋但工作正常)

CREATE TEMPORARY TABLE temp1 (
  a int, b text, c text
);
COPY temp1(a,b,c) FROM '/tmp/myfile.csv' HEADER csv;

INSERT INTO mytable(info) SELECT json_build_array(a,b,c) FROM temp1;

很丑 因为:

完美解决!

无需知道所有 CSV 列,只需提取您知道的内容。

Use at SQL CREATE EXTENSION PLpythonU;:如果命令产生类似 "could not open extension control file ... No such file" 的错误,您需要安装 pg-py extra-packages .在标准 UBUNTU (16 LTS) 中很简单,apt install postgresql-contrib postgresql-plpython.

CREATE FUNCTION get_csvfile(
  file text,
  delim_char char(1) = ',',
  quote_char char(1) = '"')
returns setof text[] stable language plpythonu as $$
  import csv
  return csv.reader(
     open(file, 'rb'),
     quotechar=quote_char,
     delimiter=delim_char,
     skipinitialspace=True,
     escapechar='\'
  )
$$;

INSERT INTO mytable(info)
  SELECT jsonb_build_array(c[1],c[2],c[3]) 
  FROM get_csvfile('/tmp/myfile1.csv') c;

split_csv() 函数是 defined herecsv.reader很靠谱(!).

未针对 big-big CSV 进行测试...但预计 Python 完成工作。


PostgreSQL 解决方法

这不是一个完美的解决方案,但它解决了主要问题,即

... big temporary table, so lost CPU, disk and my time"...

这就是我们的方法,file_fdw 的解决方法!

  1. 采用您的约定以避免文件复制和文件权限混淆... CSV 的标准文件路径。示例:/tmp/pg_myPrj_file.csv

  2. 初始化您的数据库或 SQL 带有魔术扩展的脚本,

   CREATE EXTENSION file_fdw;
   CREATE SERVER files FOREIGN DATA WRAPPER file_fdw;
  1. 对于每个 CSV 文件,myNewData.csv

    3.1。为您的新文件 ln -sf $PWD/myNewData.csv /tmp/pg_socKer_file.csv

    创建符号 link(或 scp 远程副本)

    3.2。为您的新 table 配置 file_fdw(假设 mytable)。

   CREATE FOREIGN TABLE temp1 (a int, b text, c text) 
   SERVER files OPTIONS ( 
     filename '/tmp/pg_socKer_file.csv', 
       format 'csv', 
       header 'true'
   );

PS:在 运行 SQL 脚本与 psql 之后,当遇到一些权限问题时,将 link 的所有者更改为 sudo chown -h postgres:postgres /tmp/pg_socKer_file.csv.

3.3。使用 file_fdw table 作为来源(假设填充 mytable)。

 INSERT INTO mytable(info)
 SELECT json_build_array(a,b,c) FROM temp1;

感谢@JosMac(和his tutorial)!


注意: 如果有 STDIN 方法(存在??),会很容易,避免权限问题和使用绝对路径。参见