如何将CSV复制为JSON字段

时间:2017-01-04 14:07:41

标签: postgresql csv jsonb

有没有办法将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;

丑陋因为:

  • 需要关于字段的小修知识,以及之前的CREATE TABLE

  • “大数据”需要一个大的临时表,因此丢失了CPU,磁盘和我的时间 - 表mytable对每一行都有CHECK和UNIQUEs约束。

  • ...需要多个SQL命令。

1 个答案:

答案 0 :(得分:4)

完美的解决方案!

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

在SQL CREATE EXTENSION PLpythonU;使用:如果命令产生错误,如"无法打开扩展控制文件...没有这样的文件" 你需要安装pg -py额外包裹。在标准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 非常可靠(!)。

没有针对大型CSV进行测试......但是预期Python会有效。

PostgreSQL解决方法

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

  

...大临时表,所以丢失了CPU,磁盘和我的时间" ...

这是我们这样做的方式,file_fdw的解决方法!

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

  2. 使用魔术扩展

  3. 初始化数据库或SQL脚本
       CREATE EXTENSION file_fdw;
       CREATE SERVER files FOREIGN DATA WRAPPER file_fdw;
    
    1. 对于每个CSV文件myNewData.csv

      3.1。为新文件scp

      制作符号链接(或ln -sf $PWD/myNewData.csv /tmp/pg_socKer_file.csv远程复制)

      3.2。为新表配置 file_fdw (假设为mytable)。

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

      PS:在使用psql运行SQL脚本后,遇到一些权限问题时,请按sudo chown -h postgres:postgres /tmp/pg_socKer_file.csv更改链接的所有者。

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

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

      感谢@JosMac(和his tutorial)!

      注意:如果有STDIN方法(存在??),将很容易,避免权限问题和使用绝对路径。请参阅this answer/discussion