首页 > 解决方案 > 1214:使用 COPY 命令将数据从 cvs 导入 Redshift 时 CSV 的报价格式无效

问题描述

我在 COPY 命令下运行以将数据从 CVS 导入 Redshift 并出现错误:

psql -w -U user1 -h host1 db1 --port 123 -c \
    "COPY table1 FROM 's3://bucket1/table1.csv' \  
     credentials 'aws_access_key_id=aaaaa;aws_secret_access_key=aaaa' \
     IGNOREHEADER 1 \
     csv NULL AS 'NULL' ;"

错误:加载到表“rainlab_translate_attributes”失败。检查“stl_load_errors”系统表以获取详细信息。

当我检查 stl_load_errors 时,我可以看到:

1214 CSV 的引用格式无效
似乎 \ 和 {} 导致出现在我的列值中的问题。

有没有针对此类问题的解决方法?

标签: amazon-web-servicesamazon-redshift

解决方案


问题是您的数据包含字符,这是字符"的默认值(请参阅文档)。QUOTECOPY ... CSV ...

看起来您的数据是 JSON 并且它充满了,"字符,并且它们既没有被引用也没有被转义。我相信您必须修改您的 CSV 文件才能加载它,因为目前 Redshift(并且没有其他人)可以将分隔符,,JSON 中的分隔符区分开来。

正如您将在下面阅读的那样,有多个选项如何构建您的 csv 文件,但它立即显示了该文件格式用于存储数据的所有缺点 - 例如,它可能比 JSON 更简洁,但一旦您会带来大量问题存储更复杂的东西。阅读我的建议后,考虑将您的文件格式更改为例如。JSON 在qouting方面具有更清晰的语义。

如何使用 CSV 使其工作

我假设您的 CSV 数据如下所示:

"1","app.name","{"x":"app.name","en":"dfgdggfdfdd","de":"dfdddffgf Entwicklerportal","ja":"fgdfgdfg\\\\dfgfdd\\\\fdfg\\\\gfdgf\\\\gfdgd\\\\fdgdf\\\\gfgfdg\\\\dgdfg","zh-gfdd":"gdfgdgd\\\\gfgd\\\\gfdgd\\\\fgdfdf\\\\dgfdgfd\\\\gdfgdf\\\\dgdfgfd"}"

选项 1 - 使用不同的QUOTE字符:

例如backtick,将您QUOTE 的数据更改为如下所示:

`1`,`app.name`,`{"x":"app.name","en":"dfgdggfdfdd","de":"dfdddffgf Entwicklerportal","ja":"fgdfgdfg\\\\dfgfdd\\\\fdfg\\\\gfdgf\\\\gfdgd\\\\fdgdf\\\\gfgfdg\\\\dgdfg","zh-gfdd":"gdfgdgd\\\\gfgd\\\\gfdgd\\\\fgdfdf\\\\dgfdgfd\\\\gdfgdf\\\\dgdfgfd"}`

您不必引用所有字段,只需引用包含,.

并使用此COPY命令:

psql -w -U user1 -h host1 db1 --port 123 -c \
    "COPY table1 FROM 's3://bucket1/table1.csv' \  
     credentials 'aws_access_key_id=aaaaa;aws_secret_access_key=aaaa' \
     IGNOREHEADER 1 \
     CSV QUOTE AS '`' 
     NULL AS 'NULL' ;"

选项 2 - 逃避你的QUOTE角色:

将您的数据更改为如下所示:

"1","app.name","{""x"":""app.name"",""en"":""dfgdggfdfdd"",""de"":""dfdddffgf Entwicklerportal"",""ja"":""fgdfgdfg\\\\dfgfdd\\\\fdfg\\\\gfdgf\\\\gfdgd\\\\fdgdf\\\\gfgfdg\\\\dgdfg"",""zh-gfdd"":""gdfgdgd\\\\gfgd\\\\gfdgd\\\\fgdfdf\\\\dgfdgfd\\\\gdfgdf\\\\dgdfgfd""}"

这样您就可以清楚引用字段的结束位置。然后你可以使用你原来的COPY命令。

选项 3 - 使用DELIMITER您的数据中不存在的。

那你就不需要报价了。例如|用作分隔符

将您的数据更改为如下所示:

1|app.name|{"x":"app.name","en":"dfgdggfdfdd","de":"dfdddffgf Entwicklerportal","ja":"fgdfgdfg\\\\dfgfdd\\\\fdfg\\\\gfdgf\\\\gfdgd\\\\fdgdf\\\\gfgfdg\\\\dgdfg","zh-gfdd":"gdfgdgd\\\\gfgd\\\\gfdgd\\\\fgdfdf\\\\dgfdgfd\\\\gdfgdf\\\\dgdfgfd"}

并使用此COPY命令:

psql -w -U user1 -h host1 db1 --port 123 -c \
    "COPY table1 FROM 's3://bucket1/table1.csv' \  
     credentials 'aws_access_key_id=aaaaa;aws_secret_access_key=aaaa' \
     IGNOREHEADER 1 \
     CSV QUOTE AS '`' 
     DELIMITER AS '|'
     NULL AS 'NULL' ;"

推荐阅读