Postgresql COPY空字符串为NULL无效

时间:2017-08-26 06:04:37

标签: string postgresql null copy psql

我有一个带有一些整数列的CSV文件,现在它保存为“”(空字符串)。

我想将它们复制到一个表为NULL值。

使用JAVA代码,我尝试了这些:

String sql = "COPY " + tableName + " FROM STDIN (FORMAT csv,DELIMITER ',',  HEADER true)";
String sql = "COPY " + tableName + " FROM STDIN (FORMAT csv,DELIMITER ',', NULL ''  HEADER true)";

我得到:PSQLException:错误:类型为numeric的输入语法无效:“”

String sql = "COPY " + tableName + " FROM STDIN (FORMAT csv,DELIMITER ',', NULL '\"\"'  HEADER true)";

我得到:PSQLException:错误:CSV引号字符不得出现在NULL规范中

之前有人这样做过吗?

2 个答案:

答案 0 :(得分:7)

我假设您知道数字数据类型没有"空字符串"的概念。 ('')。它是一个数字或NULL(或numeric的' NaN'但integer等不是。

看起来您是从text这样的字符串数据类型导出的,并且其中有一些实际的空字符串 - 现在表示为"" - "是默认QUOTE CSV格式的字符。

NULL将由 nothing 表示,甚至不是引号。 The manual:

  

NULL

     

指定表示空值的字符串。默认值为\N   (反斜杠-N)文本格式,以及CSV格式的未加引号的空字符串。

无法定义""通常代表NULL,因为它已经代表一个空字符串。会含糊不清。

要修复,我看到两个选项:

  1. 在送至COPY之前修改CSV文件/流并替换"" 没有。如果你的字符串中还有实际的空字符串,那么可能会很棘手 - 或""在字符串中转义文字"

  2. (我会做什么。)导入到具有相同结构的辅助临时表,但转换为integer的{​​{1}}列除外。然后text(或UPSERT?)从那里到目标表,在运行中正确转换INSERT值:

  3. integer

    会话结束时会自动删除临时表。如果在同一会话中多次运行,则只需截断现有临时表或在每次事务后删除它。

    相关:

答案 1 :(得分:0)

自Postgres 9.4起,您现在可以使用FORCE NULL。这会导致将空字符串转换为NULL。非常方便,尤其是CSV文件。

语法如下:COPY table from stdin WITH DELIMITER';' CSV FORCE NULL integerfieldname;

重要的是它没有下划线,文档(imho)中并未真正明确解释:https://www.postgresql.org/docs/current/sql-copy.html