输入以下命令时:
\copy mmcompany from '<path>/mmcompany.txt' delimiter ',' csv;
我收到以下错误:
ERROR: duplicate key value violates unique constraint "mmcompany_phonenumber_key"
我理解为什么会这样,但是我如何以插入有效条目的方式执行命令,并且会丢弃那些产生错误的命令?
答案 0 :(得分:5)
PostgreSQL不这样做的原因与它如何实现约束和验证有关。当约束失败时,它会导致事务中止。交易处于不洁净状态,无法恢复。
可以为每一行创建一个新的子事务,但这非常慢,并且首先违背了使用COPY
的目的,因此COPY
中的PostgreSQL不支持它。这次。您可以在PL / PgSQL中自己使用BEGIN ... EXCEPTION
块内的LOOP
块,从复制到临时表中的数据中选择。这种方法效果很好但可能很慢。
如果可能的话,最好在执行任何违反它们的插入之前使用SQL检查约束。这样你就可以:
CREATE TEMPORARY TABLE stagingtable(...);
\copy stagingtable FROM 'somefile.csv'
INSERT INTO realtable
SELECT * FROM stagingtable
WHERE check_constraints_here;
但是请记住并发问题。如果您尝试通过COPY
进行合并/ upsert,则必须 LOCK TABLE realtable;
在您的交易开始时,您仍然可能会出错。看起来这就是你要做的事情 - copy if not exists
。如果是这样,跳过错误绝对是错误的方法。参见:
......这是一个备受争议的问题。
答案 1 :(得分:2)
处理约束违规的一种方法是在目标表上定义触发器以处理错误。这并不理想,因为仍然存在竞争条件(如果同时加载),并且触发器具有相当高的开销。
另一种方法:将COPY复制到临时表中,并使用SQL将数据加载到目标表中,并进行一些处理以跳过现有条目。
此外,另一种有用的方法是使用pgloader