为啥 Oracle 不允许您使用相同的列同时创建主键和唯一约束?

Posted

技术标签:

【中文标题】为啥 Oracle 不允许您使用相同的列同时创建主键和唯一约束?【英文标题】:Why Oracle does not permit you to create both a primary key and unique constraint with the same columns?为什么 Oracle 不允许您使用相同的列同时创建主键和唯一约束? 【发布时间】:2015-11-05 10:21:27 【问题描述】:

试图理解约束。 这个article 说

Oracle 不允许您同时创建主键和唯一键 具有相同列的约束。

后面是一个例子:

CREATE TABLE supplier
( supplier_id numeric(10) NOT NULL,
  supplier_name varchar2(50) NOT NULL,
  contact_name varchar2(50),
  CONSTRAINT supplier_unique UNIQUE (supplier_id)
);

我是否正确理解创建的supplier_id 不能是主键?

另外,为什么不允许?因为主键在定义上是唯一的,并且仅仅对该列施加约束是没有意义的?

【问题讨论】:

我想我在这里找到了第二个问题的答案:***.com/questions/7224505/… 因为它也不会让您创建具有相同列的两个索引 这也可能是外键可能违反 PK 或唯一约束的一个因素,因此同时拥有两者会有点模棱两可 - 特别是如果您随后尝试删除其中一个? (FK 的 search_condition 列可能必须更改为指向另一个约束,并且它必须在删除之前寻找其他约束,这使得一切变得更加复杂......) 【参考方案1】:

主键和唯一约束都创建一个底层唯一索引。由于(大多数情况下)创建两次相同的索引是没有意义的,Oracle 会检查并禁止这样做。

注意关于上面的“大部分时间”:有时在同一列上同时具有 B*Tree 索引和位图索引可能是有意义的。这可以通过基于函数的索引来完成,但这是一种相当“高级的技巧”,其代价是使 Oracle 查询优化器对使用“被破解”的索引有点疯狂。

我是否正确理解为使此查询起作用,创建的supplier_id 不能是主键?

是的,在您的代码示例中,supplier_id 不能是主键,以便您可以创建对 supplier_id 的唯一约束。

【讨论】:

虽然可以针对现有索引创建任何一个约束,所以原则上两者都可以针对同一个索引? 所以代码示例中的supplier_id不能是主键? (如果是,请编辑您的答案,我会接受您作为正确答案) 在您的代码示例中,无论如何您都没有主键声明,但是好的,我已经根据您的需要编辑了我的答案。 我并不是说这意味着它是允许的 - 它不是 - 只是我不认为无法为同一列创建两个唯一索引可能是(仅) 原因 Oracle 不允许您同时拥有这两个约束,因为理论上它们无论如何都可以使用相同的索引。 @AlexPoole,你得到了我这个。是的,你是对的,现在我终于开始尝试它了——即使使用预建的唯一索引,当列上已经有一些约束时,Oracle 也不允许在列上创建唯一/主约束。 ORA-02261: such unique or primary key already exists in the table 失败。 (常识说:为什么它允许两者兼得?)谢谢。答案再更新一次。

以上是关于为啥 Oracle 不允许您使用相同的列同时创建主键和唯一约束?的主要内容,如果未能解决你的问题,请参考以下文章

oracle数据库中怎么设置一个字段的唯一性

oracle数据库中怎么设置一个字段的唯一性?

为啥 hibernate 在不同的 JVM 实例中为相同的查询创建不同的列别名?

在已经存在主键或唯一键约束的列上创建索引

为啥 Oracle 不在这里抛出“不明确的列引用”?

为啥 C++ 不允许重新绑定引用?