INSERT [...] ON CONFLICT可用于外键违规吗?

时间:2016-03-16 14:35:13

标签: sql postgresql sql-insert upsert postgresql-9.5

鉴于

=> 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;

是否可以在这里检查是否存在外键?

1 个答案:

答案 0 :(得分:7)

是的,将输入行连接到引用的表,从而删除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。)