如何使用psql\copy meta-command忽略错误

Sup*_*ero 7 postgresql error-handling psql postgresql-copy

我正在使用psqlPostgreSQL数据库和以下copy命令:

\COPY isa (np1, np2, sentence) FROM 'c:\Downloads\isa.txt' WITH DELIMITER '|'
Run Code Online (Sandbox Code Playgroud)

我明白了:

ERROR:  extra data after last expected column
Run Code Online (Sandbox Code Playgroud)

如何跳过有错误的行?

Erw*_*ter 12

如果不跳过包括Postgres 9.5在内的整个命令,则不能跳过错误.目前没有更复杂的错误处理.

\copy只是SQL的包装器COPY,通过psql引导结果.手册COPY:

COPY在第一个错误时停止操作.这不应该在a的情况下导致问题COPY TO,但目标表已经收到了a中的早期行COPY FROM.这些行将不可见或无法访问,但它们仍占用磁盘空间.如果故障发生在大型复制操作中,这可能相当于浪费大量磁盘空间.您可能希望调用 VACUUM以恢复浪费的空间.

大胆强调我的.和:

COPY FROM 如果输入文件的任何行包含比预期更多或更少的列,则会引发错误.

有一个尝试错误记录添加到COPY了在Postgres 9.0,由ASTER数据带头,但它再也没有犯过.该公司后来被Teradata收购,所以我怀疑他们仍然在追求这个项目.

修改输入文件.

如果输入文件中有一个或多个附加列,并且文件一致,则可以向表中添加虚拟列,isa然后删除它们.或者(带有生产表的清洁器)从那里导入临时登台表和INSERT选定的列(或表达式)到目标表isa.

相关答案详细说明:

  • 对于多年后偶然发现这个答案的任何人:如果您的输入数据中只有一些格式错误的行,您可以运行“\copy”命令,postgres 将报告错误所在的行号。然后,您可以使用“sed -i '5d' input.tsv”(其中 5 是行号)删除此行,并尝试再次运行“\copy”。 (4认同)
  • 对于任何读过巴拉兹解决方案的人来说,它都行不通。哪一行格式错误的错误报告不会与输入文件中的同一行协调。您必须使用 grep 搜索来查找该行并使用 sed 将其删除。IE。它报告了错误行 283678,但是 grep 后发现文件中的错误行是 126092。 (2认同)

Nul*_*lik 6

遗憾的是,25 年来 Postgres 没有用于命令-ignore-errors的标志或选项COPY。在这个大数据时代,您会获得大量脏记录,并且项目修复每个异常值的成本可能非常高。

我必须这样解决:

  1. 复制原表并调用dummy_original_table
  2. 在原始表中,创建一个如下触发器:
    CREATE OR REPLACE FUNCTION on_insert_in_original_table() RETURNS trigger AS  $$  
    DECLARE
        v_rec   RECORD;
    BEGIN
        -- we use the trigger to prevent 'duplicate index' error by returning NULL on duplicates
        SELECT * FROM original_table WHERE primary_key=NEW.primary_key INTO v_rec;
        IF v_rec IS NOT NULL THEN
            RETURN NULL;
        END IF; 
        BEGIN 
            INSERT INTO original_table(datum,primary_key) VALUES(NEW.datum,NEW.primary_key)
                ON CONFLICT DO NOTHING;
        EXCEPTION
            WHEN OTHERS THEN
                NULL;
        END;
        RETURN NULL;
    END;
Run Code Online (Sandbox Code Playgroud)
  1. 将副本运行到虚拟表中。那里不会插入任何记录,但所有记录都会插入到original_table中

psql dbname -c \copy dummy_original_table(datum,primary_key) FROM '/home/user/data.csv' delimiter E'\t'