Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql 使用什么来代替“引用”;插入。。。“在冲突中无所作为”;论博士后_Postgresql - Fatal编程技术网

Postgresql 使用什么来代替“引用”;插入。。。“在冲突中无所作为”;论博士后

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

我有以下查询,我在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 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循环来捕获唯一的_冲突和重试。