2016-03-16 51 views
5

鑑於可以將衝突INSERT [...]用於外鍵違規?

=> select * from referenced; 
referenced_id | name 
---------------+------- 
      1 | one 
      2 | two 
      3 | three 

=> select * from entries; 
entry_id | referenced_id |  name  
----------+---------------+------------------ 
     1 |    3 | references three 

其中referenced_identry_id是主鍵。

我想要一個entries的插入語句,如果entry_id已存在或引用的項目不存在,則跳過插入。第一個很容易完成:

INSERT INTO entries 
VALUES (1, 2, 'references two') 
ON CONFLICT (entry_id) DO NOTHING; 

是否有可能檢查這裏的外鍵是否存在?

回答

6

是,加入你輸入行引用的表,從而去除行,而不在FK列匹配:

INSERT INTO entries(entry_id, referenced_id, name) 
SELECT val.entry_id, val.referenced_id, val.name 
FROM (
    VALUES (1, 2, 'references two') 
     -- more? 
) val (entry_id, referenced_id, name) 
JOIN referenced USING (referenced_id) -- drop rows without matching FK 
ON  CONFLICT (entry_id) DO NOTHING; -- drop rows with duplicate id 

的UPSERT本身(INSERT ... ON CONFLICT DO NOTHING)只反應獨特的違規行爲。 The manual:

ON CONFLICT可用於指定替代操作來引發唯一約束或排除約束違規錯誤。 (請參閱下面的ON CONFLICT Clause。)

+0

確實非常好,非常感謝。感謝您澄清關於'ON CONFLICT'條款。 – peterwimsey

+0

這項工作如果插入同一張桌子上,我嘗試引用?所以像'INSERT INTO entries ... JOIN entries'? –

+2

@JuanCarlosOropeza:你可以用同樣的方式加入同一張表,只要確保連接條件只能匹配一個* single *行。否則你必須使用不同的技術。 –