我有一个 postgres 8.3.4 数据库。在三元组 UNIQ(name, id, age) 上存在一个具有唯一约束的名称表。不知何故,有几行已添加到数据库中,导致违反此约束。
我的问题是这怎么可能?当添加了违反约束的第一行时,数据库不应该抛出错误吗?
name : text
id : integer not null (fk to a id table)
age : integer
我有一个 postgres 8.3.4 数据库。在三元组 UNIQ(name, id, age) 上存在一个具有唯一约束的名称表。不知何故,有几行已添加到数据库中,导致违反此约束。
我的问题是这怎么可能?当添加了违反约束的第一行时,数据库不应该抛出错误吗?
name : text
id : integer not null (fk to a id table)
age : integer
我的猜测是你错过了NULL
价值观从不UNIQUE
的事实。
如果您多次输入,则不会出现唯一违规(NULL, 1, 20)
。(name, id, age)
两个NULL
值永远不会被认为是“相同的”。
您可以设置所有涉及的列NOT NULL
(在将 NULL 值替换为虚拟值之后)。
或者,您可以实现额外的部分索引来覆盖 NULL(在使用 清除“dupes”之后NULL
)。例如,如果您需要覆盖name
NULL 列:
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。已经进行了许多修复。
这几乎是不可行的。
很可能,您的名称中有额外的空格或类似的东西。
请发布确切的表定义。
另外,请运行此查询:
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)
并在此处发布一些返回的输出。