2017-02-20 208 views
0

在这条SQL语句如何忽略在Postgres INSERT INTO中违反外键约束的行?

INSERT INTO child (parentId, value) SELECT parentId, value FROM temptable 

child.parentId是一个外键指向parent.id。当长期运行的INSERT INTO语句(可能会插入多达几百万行)正在运行时,可能会随时删除parent表中的行。

如果child表在parent以前INSERT INTO声明中没有相应的外键开始运行,或者从child引用的parent表中的行被删除INSERT INTO运行时,我想的INSERT INTO默默地忽略该特定行(并简单地跳过插入到child违反外键约束的行)而不是整个语句失败。

我该如何做到这一点?在这种情况下,我不熟悉任何竞态条件如何工作。

回答

2

你可以尝试在SELECT锁定表parent的引用的行:但是

INSERT INTO child (parent_id, value) 
    SELECT t.parent_id, t.value 
    FROM temptable t 
    JOIN parent p ON t.parent_id = p.id 
    FOR UPDATE OF p; 

注意,这种预防性锁定可能显著增加执行时间的情况下,当表parent被其他交易的集中修改同一时间。作为一种补救措施,您可以考虑通过将数据划分为逻辑分区来执行多个事务中的插入,例如,

INSERT 
    ... 
    WHERE parent_id < 1000 

INSERT 
    ... 
    WHERE parent_id BETWEEN 1001 AND 2000 -- and so on.