我正在使用 PostgreSQL 数据库,并使用 psql
命令,使用以下的 copy
命令:
\COPY isa (np1, np2, sentence) FROM 'c:\Downloads\isa.txt' WITH DELIMITER '|'
我理解为:
ERROR: extra data after last expected column
我该如何跳过出错的行?我正在使用 PostgreSQL 数据库,并使用 psql
命令,使用以下的 copy
命令:
\COPY isa (np1, np2, sentence) FROM 'c:\Downloads\isa.txt' WITH DELIMITER '|'
我理解为:
ERROR: extra data after last expected column
我该如何跳过出错的行?如果您跳过错误,则需要跳过整个命令,包括Postgres 14。目前没有更复杂的错误处理。
\copy
只是围绕SQL COPY
的包装器,通过psql通道传输结果。 COPY
的手册:
COPY
在第一个错误处停止操作。在COPY TO
的情况下,这不应导致问题,但目标表已经接收了COPY FROM
中的早期行。这些行将不可见或无法访问,但它们仍然占用磁盘空间。如果故障发生在大型复制操作的后期,则可能会导致相当多的浪费磁盘空间。您可能希望调用VACUUM
来恢复浪费的空间。
我加粗了部分内容。并且:
COPY FROM
会在输入文件的任何一行包含比预期列数更多或更少的列时引发错误。
COPY
是一种非常快速的导入/导出数据的方法。复杂的检查和错误处理会减慢它的速度。
Postgres 9.0中曾经有一个尝试为COPY
添加错误日志记录,但它从未被提交。
修复您的输入文件。
如果您的输入文件中有一个或多个附加列,并且该文件其余部分保持一致,则可以向您的表isa
添加虚拟列,然后再删除这些列。(对于生产表来说,更干净的方法是)导入到临时暂存表中,然后从那里INSERT
所选列(或表达式)到您的目标表isa
。
相关答案详细说明:
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;
psql dbname -c \copy dummy_original_table(datum,primary_key) FROM '/home/user/data.csv' delimiter E'\t'
这里有一个解决方案——逐行导入批处理文件。虽然性能可能会慢得多,但对于您的情况可能已经足够了:
#!/bin/bash
input_file=./my_input.csv
tmp_file=/tmp/one-line.csv
cat $input_file | while read input_line; do
echo "$input_line" > $tmp_file
psql my_database \
-c "\
COPY my_table \
FROM `$tmp_file` \
DELIMITER '|'\
CSV;\
"
done
psql
的stdout/stderr和退出状态,如果退出状态为非零,则将$input_line
和捕获的stdout/stderr回显到stdin和/或追加到文件中。sed
删除报告的错误行,然后再次运行\copy
后续版本的Postgres(包括Postgres 13)将报告错误的行号。 然后,您可以使用sed
删除该行,并再次运行\copy,例如:#!/bin/bash
bad_line_number=5 # assuming line 5 is the bad line
sed ${bad_line_number}d < input.csv > filtered.csv
COPY
而言,它们将像其他列一样成为列。您的“缺失数据”错误表明您的输入文件不一致 - 或者您没有使用正确的分隔符或转义字符。无论哪种方式,我更愿意选择我提到的第二个选项:临时暂存表。但是,您也需要一个一致的文件。 - Erwin Brandstetter\copy
命令,PostgreSQL将报告错误发生的行号。然后,你可以使用sed -i '5d' input.tsv
(其中5是行号)删除此行,并尝试再次运行\copy
。 - Botond Balázs