13

给定

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

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

wherereferenced_identry_id是主键。

如果已存在或引用的项目不存在,我想要一个entries跳过插入的插入语句。entry_id第一个很容易做到:

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

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

4

1 回答 1

15

是的,将您的输入行连接到引用的表,从而删除 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) 仅对独特的违规行为作出反应。手册:

ON CONFLICT可用于指定引发唯一约束或排除约束违规错误的替代操作。(见下面的冲突条款。)

由于VALUES表达式现在不INSERT直接附加到一个,列类型不是从目标表派生的。使用非基本类型操作时,您可能需要显式转换输入值。看:

于 2016-03-16T15:07:35.207 回答