Postgresql 使用什么来代替“引用”;插入。。。“在冲突中无所作为”;论博士后
我有以下查询,我在postgres 9.5中使用:Postgresql 使用什么来代替“引用”;插入。。。“在冲突中无所作为”;论博士后,postgresql,Postgresql,我有以下查询,我在postgres 9.5中使用: INSERT INTO knowledge_state (SELECT learnerid learner_id, lo_id FROM qb_lo_tag WHERE qb_id = NEW.qb_id) ON CONFLICT DO NOTHING ; 不幸的是,我不能在某些服务器上使用Postgres9.5,我需要将其转换为9.5之前的友好查询。 我构建了下面的查询,但对我来说它似乎复杂得多,我认为可能会有更简单的查询 FOR row
INSERT INTO knowledge_state
(SELECT learnerid learner_id, lo_id FROM qb_lo_tag WHERE qb_id = NEW.qb_id)
ON CONFLICT DO NOTHING ;
不幸的是,我不能在某些服务器上使用Postgres9.5,我需要将其转换为9.5之前的友好查询。
我构建了下面的查询,但对我来说它似乎复杂得多,我认为可能会有更简单的查询
FOR rows IN SELECT lo_id FROM knowledge_state
WHERE learner_id = learnerid
AND lo_id IN (SELECT lo_id FROM qb_lo_tags WHERE qb_id = New.qb_id) LOOP
INSERT INTO knowledge_state (lo_id, learner_id) SELECT rows.lo_id, learnerid
WHERE NOT EXISTS (SELECT * FROM knowledge_state WHERE lo_id = rows.lo_id AND learner_id = learnerid);
END LOOP;
我很想听听关于如何简化此查询的想法。只需做你正在做的事情,不需要循环:
INSERT INTO knowledge_state (lo_id, learner_id)
SELECT a.lo_id, a.learnerid
FROM qb_lo_tag a
WHERE a.qb_id = NEW.qb_id
and NOT EXISTS (SELECT * FROM knowledge_state b
WHERE b.lo_id = a.lo_id AND b.learner_id = a.learnerid);
当然,您可以在knowledge_state(lo_id,learner_id)上添加索引,以使其更快(on Conflict表示唯一约束或其他约束,而唯一约束表示索引)。错误。这在存在并发事务的情况下是不正确的;如果同时运行两个密钥,则仍可能引发重复密钥错误。必须首先
锁定表
,或者在plpgsql中使用循环
,以捕获重复密钥异常并重试。这与upsert的问题是一样的。@CraigRinger我的查询版本是否可以免除您上面描述的问题?@Clémentine否。想象一下,如果两个并发会话都执行了插入。。。如果不存在(同时选择…
)。不存在的WHERE
对它们都是真的,因为它们都找不到行。因此,两者都将继续执行INSERT
。一个会失败。这是事务可见性规则的结果,特别是防止脏读,再加上唯一索引部分违反事务隔离以确保唯一性这一事实。您必须锁定表或使用plpgsql循环来捕获唯一的_冲突和重试。