【问题标题】:PG COPY error: invalid input syntax for integerPG COPY 错误:整数的输入语法无效
【发布时间】:2013-08-20 07:35:06
【问题描述】:

运行 COPY 会导致 ERROR: invalid input syntax for integer: "" 错误消息给我。我错过了什么?

我的/tmp/people.csv 文件:

"age","first_name","last_name"
"23","Ivan","Poupkine"
"","Eugene","Pirogov"

我的/tmp/csv_test.sql 文件:

CREATE TABLE people (
  age        integer,
  first_name varchar(20),
  last_name  varchar(20)
);

COPY people
FROM '/tmp/people.csv'
WITH (
  FORMAT CSV,
  HEADER true,
  NULL ''
);

DROP TABLE people;

输出:

$ psql postgres -f /tmp/sql_test.sql
CREATE TABLE
psql:sql_test.sql:13: ERROR:  invalid input syntax for integer: ""
CONTEXT:  COPY people, line 3, column age: ""
DROP TABLE

琐事:

  • PostgreSQL 9.2.4

【问题讨论】:

  • 如果它说是哪一行/列导致了问题,那就太有用了:(

标签: postgresql csv import copy


【解决方案1】:

错误:整数的无效输入语法:“”

"" 不是有效整数。 PostgreSQL 在 CSV 中默认接受 unquoted 空白字段为 null,但 "" 会像这样写:

SELECT ''::integer;

因为同样的原因而失败。

如果您想处理包含空整数引用的空字符串之类的 CSV,您需要通过预处理器将其提供给 PostgreSQL,该预处理器可以对其进行整理。 PostgreSQL 的 CSV 输入无法理解 CSV 的所有奇怪而奇妙的可能滥用。

选项包括:

  • 将其加载到电子表格中并导出 CSV;
  • 使用 Python csv 模块、Perl Text::CSV 等对其进行预处理;
  • 使用 Perl/Python/whatever 加载 CSV 并将其直接插入 DB
  • 使用 CloverETL、Talend Studio 或 Pentaho Kettle 等 ETL 工具

【讨论】:

  • 我的“预处理”只是搜索并用空白替换"",但我只有几行,这可能会导致较大的 CSV 文件出错,但对于我的简单用例。
【解决方案2】:

我认为最好将 csv 文件更改为:

"age","first_name","last_name"
23,Ivan,Poupkine
,Eugene,Pirogov

也可以像这样定义表格

CREATE TABLE people (
  age        varchar(20),
  first_name varchar(20),
  last_name  varchar(20)
);

复制后可以转换空字符串:

select nullif(age, '')::int as age, first_name, last_name
from people

【讨论】:

  • 您可以在导入时对所有列使用text 类型。无论如何,PostgreSQL 都不关心varchar 的长度。
【解决方案3】:

最终使用csvfix

csvfix map -fv '' -tv '0' /tmp/people.csv > /tmp/people_fixed.csv

如果您确定哪些列是integerfloat,您可以只指定它们:

csvfix map -f 1 -fv '' -tv '0' /tmp/people.csv > /tmp/people_fixed.csv

如果不指定确切的列,可能会遇到明显的副作用,即空白字符串将变成带有0 字符的字符串。

【讨论】:

  • 这是旧版本文档的链接 - 最新版本始终位于 code.google.com/p/csvfix
  • 我刚刚在 CSV 中搜索并替换了 "" 的空白
【解决方案4】:

我在带有 COPY 语句的 postgres .sql 文件上遇到了同样的错误,但我的文件是 tab-separated 而不是 comma-separated 和引用 .

我的错误是我急切地从 github 复制/粘贴文件内容,但在此过程中,所有选项卡都转换为空格,因此出现错误。我必须下载并保存原始文件才能获得一份好的副本。

【讨论】:

    【解决方案5】:

    这应该可以在您不修改源 csv 文件的情况下工作:

    alter table people alter column age type text;
    copy people from '/tmp/people.csv' with csv;
    

    【讨论】:

      【解决方案6】:

      加载“|”时出现此错误尽管我的输入文件中没有 '"' 字符,但分隔 CSV 文件。原来我忘记指定 FORMAT:

      COPY ... FROM ... WITH (格式 CSV, DELIMITER '|')。

      【讨论】:

        【解决方案7】:

        有办法解决"",整数列中引用的空字符串为空, 使用 FORCE_NULL 选项:

        \copy table_name FROM 'file.csv' with (FORMAT CSV, FORCE_NULL(column_name));
        

        参见 postgresql 文档,https://www.postgresql.org/docs/current/static/sql-copy.html

        【讨论】:

          【解决方案8】:
          CREATE TABLE people (
            first_name varchar(20),
            age        integer,
            last_name  varchar(20)
          );
          

          "first_name","age","last_name" 伊万,23,波普金 尤金,,皮罗戈夫

          使用 (delimiter ';', null ''); 复制 'file.csv' 中的人员;

          select * from people;
          

          就在第一列.....

          【讨论】:

          • 我猜你的意思是:分隔符','
          【解决方案9】:

          在寻找解决方案时遇到了这个问题,想补充一下,我可以通过在 copy_from 调用中添加“null”参数来解决这个问题:

          cur.copy_from(f, tablename, sep=',', null='')
          

          【讨论】:

          • 这看起来像是 Python 的一个简短的 sn-p,也许你应该提供一个完整的例子......
          【解决方案10】:

          使用以下命令在一行中从 CSV 复制数据,而无需转换和更改数据类型。 请用您的字符串替换“NULL”,这会在复制数据中产生错误

          copy table_name from 'path to csv file' (format csv, null "NULL", DELIMITER ',', HEADER);
          

          【讨论】:

          • 在 pgAdmin 4.29 和 PostgreSQL 12 上与我合作。
          【解决方案11】:

          令人难以置信的是,我对相同错误的解决方案是重新排列列。对于其他执行上述解决方案但仍未解决错误的人。

          我显然不得不排列我的 CSV 文件中的列以匹配 PGADmin 中列出的表中的相同序列。

          【讨论】:

            【解决方案12】:

            全部在python中(使用psycopg2),首先创建空表,然后使用copy_expert将csv加载到其中。它应该处理空值。

            import psycopg2
            conn = psycopg2.connect(host="hosturl", database="db_name", user="username", password="password")
            cur = conn.cursor()
            cur.execute("CREATE TABLE schema.destination_table ("
                        "age integer, "
                        "first_name varchar(20), "
                        "last_name varchar(20)"
                        ");")
            
            with open(r'C:/tmp/people.csv', 'r') as f:
                next(f)  # Skip the header row. Or remove this line if csv has no header.
                conn.cursor.copy_expert("""COPY schema.destination_table FROM STDIN WITH (FORMAT CSV)""", f)
            

            【讨论】:

              猜你喜欢
              • 2018-10-22
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-07-21
              • 2014-03-30
              • 1970-01-01
              • 2014-07-17
              • 2012-12-21
              相关资源
              最近更新 更多