2017-02-20 209 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.