【问题标题】:CSV import via COPY FROM won't work with NULL values contained通过 COPY FROM 导入 CSV 不适用于包含的 NULL 值
【发布时间】:2011-06-29 02:22:24
【问题描述】:

我有一个 CSV 文件,想通过我的数据库中的 Postgres 命令“COPY x FROM y”将其导入。该数据库有两列:名为“id”的列(串行,不允许 NULL)和“值”列(varchar,允许 NULL 并应用约束)。我将在下面为测试数据库提供简短的创建脚本。 CSV 是通过从 OpenOffice 电子表格中导出来获得的。最后还提供了 CSV 内容。

我的问题:

执行以下命令时...

COPY mytable FROM '/tmp/testdata.csv' CSV HEADER NULL AS E'\N';

...我收到此错误消息:

ERROR:  value for domain car_manufacturer violates check constraint "car_manufacturer_format"
CONTEXT:  COPY mytable, line 3, column value: "\N"

********** Error **********

ERROR: value for domain car_manufacturer violates check constraint "car_manufacturer_format"
SQL state: 23514
Context: COPY mytable, line 3, column value: "\N"

这是CSV文件的内容(直接从OpenOffice导出,所以应该符合标准):

"ID","value"
1,"Mercedes"
2,"\N"

显然,Postgres 在理解我的 CSV 文件中的“\N”是一个 NULL 值(在本列中实际上是允许的)方面存在一些问题。首先,它根据约束检查整个字符串 "\N"。由于它不符合约束中定义的 RegexPattern,它会提供上面提到的错误。我尝试了对我的 COPY-FROM-Command 的一些修改,但都没有成功导入。

简而言之:我需要一个解决方案,允许 Postgres 我通过 copy-from-command 导入 csv,此外,允许在 string/varchar 中有“\N”条目表示 NULL 值的列。

我真的需要使用 Copy 命令来完成,因为我想通过使用脚本来自动化导入过程。当使用 phpPGAdmin 导入 CSV 时,一切正常。这是因为 phpPgAdmin 正在向 postgres 服务器发送 INSERT-Commands。所以显然没有使用“copy from”-命令...

其他信息:

这是数据库的创建脚本

CREATE DOMAIN car_manufacturer AS VARCHAR (100) CONSTRAINT car_manufacturer_format CHECK
(VALUE SIMILAR TO '[A-Z][A-Za-z]+|');
COMMENT ON DOMAIN car_manufacturer IS 'The name of a car manufacturer (e.g, Ford, BMW, Chrysler, Mercedes etc.)';

CREATE TABLE mytable
(
  "ID" serial NOT NULL,
  "value" car_manufacturer,
  CONSTRAINT pk_mytable PRIMARY KEY ("ID")
)
WITH (
  OIDS=FALSE
);
ALTER TABLE mytable OWNER TO postgres;

提前非常感谢!

干杯, 菲利普

PS:我的例子是为了向你展示实际的问题。所以,请不要被这个例子的琐碎所困扰:-)

【问题讨论】:

    标签: database file postgresql csv import


    【解决方案1】:

    我通常不对字符字段使用引号,而是使用不同的分隔符来避免嵌入逗号的困难,例如'|'将开放式办公室导出到 csv 时。 然后在导入时指定分隔符并转义反斜杠以指定空 E'\\N'。

    【讨论】:

    • 嗨 Gavin,使用 E'\\N' 而不是 E'\N' 没有帮助。将出现相同的确切错误消息。此外,引用字符字段是一种通用标准,OpenOffice 和其他 CSV 导出器也使用它。分隔符默认为逗号。我的 CSV 坚持这个标准,因此应该可以毫无问题地导入。 "\N" 在 Postgres-Specs 中也是一个有效的 Null-Value 字符串,必须在这种情况下使用,因为我根本不允许更改它。
    • 副本将 "\N" 解释为字符串值,这就是我建议上述方法的原因,但如果你不能使用它,那么我想你可以在表上放置一个插入前触发器将“\N”值转换为空!
    • 我同意复制命令可能将“\N”误解为字符串。但是,创建插入前触发器与其说是解决方案,不如说是一种变通方法。看,我必须在数据库的每个表上创建一个触发器,至少对于我计划定期导入 CSV 的所有表。这种解决方案缺乏很大的灵活性。我确信必须有一种方法可以让单行命令正常工作(如果它不是错误的话)......
    • 我又来了。我认为最好的解决方案是——正如 Gavin 在他最初的回复中所建议的那样——通过不使用双引号从 OpenOffice 导出数据并选择唯一的分隔符(例如 |)。虽然这不是标准的 csv 格式,但它会为我的问题提供最快、最有效的解决方案。问候
    【解决方案2】:

    “\N”是一个可以解释为“换行”命令的值。

    尝试使用其他字符,例如“@”。

    【讨论】:

      猜你喜欢
      • 2012-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-25
      • 1970-01-01
      • 1970-01-01
      • 2017-07-21
      • 1970-01-01
      相关资源
      最近更新 更多