【问题标题】:rows that violate unique constraints违反唯一约束的行
【发布时间】:2012-05-03 05:47:12
【问题描述】:

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

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

名称:文本
id : 不为空的整数(fk 到 id 表)
年龄:整数

【问题讨论】:

  • PostgreSQL 8.3 不再受支持。如果由于某种奇怪的原因无法更新到当前版本 (9.x),那么您至少应该更新到最新的 8.3 版本,即 8.3.18。
  • 你确定名字是一样的吗?您是否控制了尾随空格?而且,正如许多人已经评论的那样,升级到当前版本的 PostgreSQL 是明智之举:postgresql.org/support/versioning

标签: database postgresql constraints unique-constraint


【解决方案1】:

这几乎不可行。

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

请发布确切的表定义。

另外,请运行以下查询:

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)

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

【讨论】:

    【解决方案2】:

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

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

    或者您可以实现additional partial indexes 来覆盖NULL(在使用NULL 清除“欺骗”之后)。例如,如果您需要为 NULL 覆盖 name 列:

    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),但这些都没有第二次。我最近写了a more detailed assessment for this case on dba.SE

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

    【讨论】:

    • 所有三列都受非空约束保护
    • @Finslicer:您可能想编辑您的问题。那里的信息不反映您在此处评论的内容。
    猜你喜欢
    • 2020-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-03
    • 2014-11-06
    • 1970-01-01
    相关资源
    最近更新 更多