3

我有一个 postgres 8.3.4 数据库。在三元组 UNIQ(name, id, age) 上存在一个具有唯一约束的名称表。不知何故,有几行已添加到数据库中,导致违反此约束。

我的问题是这怎么可能?当添加了违反约束的第一行时,数据库不应该抛出错误吗?

name : text
id : integer not null (fk to a id table)
age : integer

4

2 回答 2

5

我的猜测是你错过了NULL价值观从不UNIQUE的事实。
如果您多次输入,则不会出现唯一违规(NULL, 1, 20)(name, id, age)两个NULL值永远不会被认为是“相同的”。

您可以设置所有涉及的列NOT NULL(在将 NULL 值替换为虚拟值之后)。

或者,您可以实现额外的部分索引来覆盖 NULL(在使用 清除“dupes”之后NULL)。例如,如果您需要覆盖nameNULL 列:

CREATE UNIQUE INDEX tbl_id_age_name_null_idx ON my_table (id, age)
WHERE name IS NULL;

然后,您的表中可以有 ('pete', 1, 20) 和 ('jane', 1, 20) 和 (NULL, 1, 20) for (name, id, age),但这些都不是第二次. 我最近在 dba.SE 上为这个案例写了更详细的评估。

顺便说一句:您应该考虑更新您的 PostgreSQL 版本。最好到当前版本 9.1。或者至少到最新的版本 8.3.18。已经进行了许多修复。

于 2012-04-22T15:06:28.617 回答
4

这几乎是不可行的。

很可能,您的名称中有额外的空格或类似的东西。

请发布确切的表定义。

另外,请运行此查询:

SELECT  q2.*
FROM    (
        SELECT  name, id, age
        FROM    mytable
        GROUP BY
                name, id, age
        HAVING  COUNT(*) > 1
        ) q
JOIN    mytable q2
ON      (q2.name, q2.id, q2.age) IS NOT DISTINCT FROM (q.name, q.id, q.age)

并在此处发布一些返回的输出。

于 2012-04-22T09:03:40.543 回答