将CSV文件复制到临时表

vaj7vani  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(149)

我有一个4列的临时表

CREATE TEMP TABLE tmp_import (
        a varchar(128), 
        b varchar, 
        c varchar(256), 
        d integer default null
        ) ON COMMIT DROP

字符串
我想复制数据从一个csv文件到这个临时表与命令

COPY tmp_import FROM STDIN WITH ( DELIMITER ';', FORMAT 'csv', ENCODING 'UTF-8', HEADER 'true')


CSV文件头可能有3或4列,如a;B;c;da;B;c,d列是可选的。如下所示;

a;b;c;d
31641212545;2021-01-01 11:00:00;http://www.google.nl;1
31641342545;2021-01-01 11:00:00;http://www.google.nl;1
31641310545;2021-01-01 11:00:00;http://www.google.nl;1
31641300545;2021-01-01 11:00:00;http://www.google.nl;1


a;b;c
31641212545;2021-01-01 11:00:00;http://www.google.nl
31641342545;2021-01-01 11:00:00;http://www.google.nl
31641310545;2021-01-01 11:00:00;http://www.google.nl
31641300545;2021-01-01 11:00:00;http://www.google.nl


COPY命令运行4个头的CSV文件,但运行3个头时失败。
引发的异常

org.postgresql.util.PSQLException: ERROR: missing data for column "d"
  Where: COPY tmp_import, line 2: "123456;2021-01-01 11:00:00;http://www.google.nl"


如何修复此查询或命令以支持3和4个头,并为缺少可选的d头插入null?

li9yvcax

li9yvcax1#

您不能用一个命令同时处理这两种情况,但是您可以指示它分别处理第二种情况:demo

copy (select '') to program $$
mkdir /tmp/myimports/ ;
echo 'a;b;c;d'   > /tmp/myimports/mycsv  ; 
echo 'a1;b1;c1;1'>>/tmp/myimports/mycsv  ;
echo 'a;b;c'     > /tmp/myimports/mycsv2 ;
echo 'a2;b2;c2'  >>/tmp/myimports/mycsv2
$$;

COPY tmp_import FROM '/tmp/myimports/mycsv' 
WITH ( DELIMITER ';', FORMAT 'csv', ENCODING 'UTF-8', HEADER 'true');
TABLE tmp_import;

字符串
| 一|B| C| D|
| --|--|--|--|
| A1| B1| C1| 1 |
请注意表名后面的显式列名列表:

COPY tmp_import(a,b,c) FROM '/tmp/mycsv2' 
WITH ( DELIMITER ';', FORMAT 'csv', ENCODING 'UTF-8', HEADER 'true');

TABLE tmp_import;


| 一|B| C| D|
| --|--|--|--|
| A1| B1| C1| 1 |
| A2| B2| C2| * 空 *|
你可以通过捕捉异常来切换:

do $f$
  declare v_file text;
begin
  create temp table my_files(f text);
  copy my_files from program $$find /tmp/myimports/ -type f $$;
  for v_file in select f from my_files loop
    begin
    execute format($c$COPY tmp_import FROM %1$L
                      WITH ( DELIMITER ';', 
                             FORMAT 'csv', 
                             ENCODING 'UTF-8', 
                             HEADER 'true');
                   $c$, v_file);
    exception when others then
    execute format($c$COPY tmp_import(a,b,c) FROM %1$L
                      CSV DELIMITER ';' ENCODING 'UTF-8' HEADER;
                   $c$, v_file);
    end;
   end loop;
end $f$;

o7jaxewo

o7jaxewo2#

如果CSV文件的列比表少,则必须指定列列表,如

COPY tmp_import (a, b, c) FROM STDIN;

字符串
由于您可能无法提前知道文件的外观,因此可以按以下步骤操作:

  • 试着用问题中的COPY语句加载文件
  • 如果没有错误,就完成了
  • 如果存在错误,则捕获它并运行带有列列表的COPY语句

相关问题