在PostgreSQL中使用COPY FROM使用TIME ZONE加载NULL TIMESTAMP

bbe*_*ort 5 csv postgresql

我有一个CSV文件,正尝试使用该COPY FROM命令将其加载到PostgreSQL 9.2.4数据库中。特别是,有一个时间戳字段允许为null,但是当我加载“ null values”(实际上只是"")时,出现以下错误:

ERROR:  invalid input syntax for type timestamp with time zone: ""
Run Code Online (Sandbox Code Playgroud)

CSV文件示例如下所示:

id,name,joined
1,"bob","2013-10-02 15:27:44-05"
2,"jane",""
Run Code Online (Sandbox Code Playgroud)

SQL如下所示:

CREATE TABLE "users"
(
    "id" BIGSERIAL NOT NULL PRIMARY KEY,
    "name" VARCHAR(255),
    "joined" TIMESTAMP WITH TIME ZONE,
);

COPY "users" ("id", "name", "joined")
    FROM '/path/to/data.csv'
    WITH (
        ENCODING 'utf-8',
        HEADER 1,
        FORMAT 'csv'
    );
Run Code Online (Sandbox Code Playgroud)

根据文档,空值应由不包含引号字符的空字符串表示,"在这种情况下为双引号():

空值

指定表示空值的字符串。默认值为文本格式\ N(反斜杠-N),以及CSV格式的无引号的空字符串。对于不想将空值与空字符串区分开的情况,甚至可能以文本格式使用空字符串。使用二进制格式时,不允许使用此选项。

注意:使用COPY FROM时,与该字符串匹配的任何数据项都将存储为空值,因此您应确保使用与COPY TO相同的字符串。

我已经尝试过该选项,NULL ''但这似乎没有任何影响。请咨询!

ale*_*ius 5

不带引号的空字符串正常工作:

id,name,joined
1,"bob","2013-10-02 15:27:44-05"
2,"jane",

select * from users;
id | name |         joined
----+------+------------------------
 1 | bob  | 2013-10-03 03:27:44+07
 2 | jane |
Run Code Online (Sandbox Code Playgroud)

也许使用 sed 将“”替换为空字符串会更简单。


Erw*_*ter 1

FORCE_NULLPostgres 9.4+ 中的选项将COPY FROM是解决您的问题的最优雅的方式。根据文档:

FORCE_NULL

将指定列的值与空字符串进行匹配,即使它已被引用,如果找到匹配项,则将该值设置为NULL。在默认情况下,空字符串为空,这会将带引号的空字符串转换为NULL. COPY FROM仅在和 使用CSV格式时才允许使用此选项。

当然,它会转换所有列中的所有匹配值。

在旧版本中,您可以COPY使用具有相同表布局的临时表text- 除了问题列的数据类型。然后修复有问题的值,然后INSERT从那里: