我有一个带有一些整数列的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规范中
之前有人这样做过吗?
答案 0 :(得分:7)
我假设您知道数字数据类型没有"空字符串"的概念。 (''
)。它是一个数字或NULL(或numeric
的' NaN'但integer
等不是。
看起来您是从text
这样的字符串数据类型导出的,并且其中有一些实际的空字符串 - 现在表示为""
- "
是默认QUOTE
CSV格式的字符。
NULL将由 nothing 表示,甚至不是引号。 The manual:
NULL
指定表示空值的字符串。默认值为
\N
(反斜杠-N)文本格式,以及CSV格式的未加引号的空字符串。
您无法定义""
通常代表NULL
,因为它已经代表一个空字符串。会含糊不清。
要修复,我看到两个选项:
在送至COPY
之前修改CSV文件/流并替换"" 没有。如果你的字符串中还有实际的空字符串,那么可能会很棘手 - 或""
在字符串中转义文字"
。
(我会做什么。)导入到具有相同结构的辅助临时表,但转换为integer
的{{1}}列除外。然后text
(或UPSERT?)从那里到目标表,在运行中正确转换INSERT
值:
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