CSV 中引用的雪花空值会破坏 PostgreSQL 卸载

Posted

技术标签:

【中文标题】CSV 中引用的雪花空值会破坏 PostgreSQL 卸载【英文标题】:Snowflake null values quoted in CSV breaks PostgreSQL unload 【发布时间】:2021-04-09 16:15:39 【问题描述】:

我正在尝试将数据从 Snowflake 转移到 Postgresql,为此我首先以 CSV 格式将其加载到 s3 中。在表格中,文本中可能会出现逗号,因此我使用FIELD_OPTIONALLY_ENCLOSED_BY雪花卸载选项来引用有问题的单元格的内容。但是,当这种情况发生 + 空值时,我无法为 PostgreSQL 提供有效的 CSV。 我创建了一个简单的表格供您理解问题。这里是:

CREATE OR REPLACE TABLE PUBLIC.TEST(
    TEXT_FIELD VARCHAR(),
    NUMERIC_FIELD INT
);
INSERT INTO PUBLIC.TEST VALUES
    ('A', 1),
    (NULL, 2),
    ('B', NULL),
    (NULL, NULL),
    ('Hello, world', NULL)
;
COPY INTO @STAGE/test
FROM PUBLIC.TEST
FILE_FORMAT = (
    COMPRESSION = NONE,
    TYPE = CSV,
    FIELD_OPTIONALLY_ENCLOSED_BY = '"'
    NULL_IF = ''
)
OVERWRITE = TRUE;

Snowflake 将从中创建以下 CSV

"A",1
"",2
"B",""
"",""
"Hello, world",""

但在那之后,我无法将这个 CSV 原样复制到 PostgreSQL 表中。 甚至从 PostgreSQL 文档中我们想到了 NULL 选项:

Specifies the string that represents a null value. The default is \N (backslash-N) in text format, and an unquoted empty string in CSV format.

未在 PostgreSQL COPY INTO 中设置 COPY 选项将导致卸载失败。实际上它不会起作用,因为我们还必须使用 QUOTE 指定使用的报价。这里是QUOTE '"'

因此在 POSTGRESQL 卸载期间,使用:FORMAT csv, HEADER false, QUOTE '"' 将给出:

DataError: invalid input syntax for integer: "" CONTEXT:  COPY test, line 3, column numeric_field: ""

FORMAT csv, HEADER false, NULL '""', QUOTE '"' 会给出:

NotSupportedError: CSV quote character must not appear in the NULL specification

仅供参考,为了测试 s3 中的卸载,我将在 PostgreSQL 中使用此命令:

CREATE IF NOT EXISTS TABLE PUBLIC.TEST(
  TEXT_FIELD VARCHAR(),
  NUMERIC_FIELD INT
);
CREATE EXTENSION IF NOT EXISTS aws_s3 CASCADE;
SELECT aws_s3.table_import_from_s3(
'PUBLIC.TEST',
'',
'(FORMAT csv, HEADER false, NULL ''""'', QUOTE ''"'')',
'bucket',
'test_0_0_0.csv',
'aws_region'
)

非常感谢您对我可以做些什么来实现它的任何想法?我很想找到一个不需要修改雪花和 postgres 之间的 csv 的解决方案。我认为这是雪花方面的一个问题,因为引用空值实际上没有意义。但 PostgreSQL 也无济于事。

【问题讨论】:

【参考方案1】:

当您将 NULL_IF 值设置为 '' 时,您实际上是在告诉 Snowflake 将 NULLS 转换为 BLANK,然后将其引用。当您从 Snowflake 中复制时,复制选项在某种意义上是“向后”的,NULL_IF 的行为更像是 IFNULL

这是我将在 Snowflake 端使用的代码,它会在您的 CSV 文件中产生一个不带引号的空字符串:

FILE_FORMAT = (
    COMPRESSION = NONE,
    TYPE = CSV,
    FIELD_OPTIONALLY_ENCLOSED_BY = '"'
    NULL_IF = ()
)

【讨论】:

非常感谢,这正是我想要的 :)

以上是关于CSV 中引用的雪花空值会破坏 PostgreSQL 卸载的主要内容,如果未能解决你的问题,请参考以下文章

读取 csv 文件时雪花句柄为空

雪花 - 查询变体中的空值

spark df.write 引用所有字段,但不引用空值

重复的 ID 值会破坏 jQuery 选择器吗?

使用雪花连接器和 COPY INTO 功能将 csv 上传到雪花时如何指定分隔符

向 geom_col 添加值会破坏整个情节