PostgreSQL:更新命令中唯一约束重复的键值。

8

在执行UPDATE查询时,我们收到了以下错误信息:

ERROR:  duplicate key value violates unique constraint "tableA_pkey"
DETAIL:  Key (id)=(47470) already exists.

然而,我们的UPDATE查询不会影响主键。这是一个简化版本:

UPDATE tableA AS a
SET
    items = (
        SELECT array_to_string(
            array(
                SELECT b.value
                FROM tableB b
                WHERE b.a_id = b.id
                GROUP BY b.name
            ),
            ','
        )
    )
WHERE
    a.end_at BETWEEN now() AND  now() - interval '1 day';

我们确保了主键序列已经同步:
\d tableA_id_seq

这将产生:

    Column     |  Type   |          Value           
---------------+---------+--------------------------
 sequence_name | name    | tableA_id_seq
 last_value    | bigint  | 50364
 start_value   | bigint  | 1
 increment_by  | bigint  | 1
 max_value     | bigint  | 9223372036854775807
 min_value     | bigint  | 1
 cache_value   | bigint  | 1
 log_cnt       | bigint  | 0
 is_cycled     | boolean | f
 is_called     | boolean | t

查找最大表索引:

select max(id) from tableA;

我们得到了一个较低的值:
  max  
-------
 50363
(1 row)

你有没有想过为什么会出现这样的行为?如果我们排除掉有问题的 id,它就能正常工作。

另一个奇怪的现象是,将上一个更新语句替换为:

UPDATE tableA AS a
SET
    items = (
        SELECT array_to_string(
            array(
                SELECT b.value
                FROM tableB b
                WHERE b.a_id = b.id
                GROUP BY b.name
            ),
            ','
        )
    )
WHERE a.id = 47470;

它工作得很好。我们是否有遗漏的内容?

编辑:触发器

我在这个表上没有用户定义的触发器:

SELECT t.tgname, c.relname
FROM pg_trigger t
JOIN pg_class c ON t.tgrelid = c.oid
WHERE
    c.relname = 'tableA'
    AND
    t.tgisinternal = false
;

没有返回任何行。

注意:我使用的是psql (PostgreSQL) 9.3.4版本。


1
表A上有任何更新触发器吗? - pozs
1
@JonathanPetitcolas 所有用户定义的触发器(WHERE pg_trigger.tgisinternal = FALSE),在更新之前和之后触发,包括触发器函数的主体。 - pozs
1
没有用户定义的触发器。 :( - Jonathan Petitcolas
你定义了一些规则吗? - Asmir Mustafic
你正在使用某种复制系统吗? - Asmir Mustafic
显示剩余4条评论
1个回答

2

我不确定问题的具体原因。但是,删除与已存在id相对应的两个(不重要的)记录解决了该问题。


如果你的答案对你有用的话,你应该接受自己的答案。 - John

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接