如何忽略Postgres INSERT INTO中违反外键约束的行?

时间:2017-02-20 22:53:27

标签: sql postgresql foreign-keys sql-insert

在这个sql语句中

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

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

如果child表在parent 之前没有相应的外键 INSERT INTO语句开始运行,或parent中有一行从child引用的表已被删除INSERT INTO正在运行,我希望INSERT INTO默默地忽略该特定行(并且只是跳过插入child违反外键约束的行,而不是整个语句失败。

我怎样才能做到这一点?我不熟悉在这种情况下任何竞争条件如何运作。

1 个答案:

答案 0 :(得分:2)

您可以尝试在parent中锁定表SELECT的引用行:

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.