Oracle唯一约束和唯一索引

a1e*_*x07 38 oracle unique-key

有人可以澄清没有唯一约束(Oracle)的唯一索引的目的是什么?例如,

create table test22(id int, id1 int, tmp varchar(20));
create unique index idx_test22 on test22(id);
insert into test22(id, id1, tmp) values (1, 2, 'aaa'); // ok
insert into test22(id, id1, tmp) values (1, 2, 'aaa'); // fails, ORA-00001: unique   
  // constraint (TEST.IDX_TEST22) violated
Run Code Online (Sandbox Code Playgroud)

到目前为止看起来有一个约束.但

create table test33(id int not null primary key, 
test22_id int not null, 
foreign key(test22_id) references test22(id) );
Run Code Online (Sandbox Code Playgroud)

也失败了"ORA-02270: no matching unique or primary key for this column-list".我完全被这种行为搞糊涂了.有没有约束?

有很多文章解释了为什么可以在没有唯一索引的情况下获得唯一约束; 这很清楚,也很有道理.但是,我不理解没有约束的唯一索引的原因.

Jus*_*ave 51

约束和索引是单独的逻辑实体.例如,唯一约束在USER_CONSTRAINTS(或ALL_CONSTRAINTSDBA_CONSTRAINTS)中可见.索引在USER_INDEXES(ALL_INDEXESDBA_INDEXES)中可见.

虽然可以(有时是必要的)使用非唯一索引强制执行唯一约束,但索引会强制执行唯一约束.例如,使用非唯一索引强制执行可延迟的唯一约束.如果在列上创建非唯一索引并随后创建唯一约束,则还可以使用该非唯一索引来强制执行唯一约束.

实际上,唯一索引的作用非常类似于唯一的,不可延迟的约束,因为它引发了与唯一约束的实现相同的错误,因为唯一约束的实现使用了索引.但它并不完全相同,因为没有约束.因此,正如您所见,没有唯一约束,因此您无法创建引用该列的外键约束.

在某些情况下,您可以创建无法创建唯一约束的唯一索引.例如,基于函数的索引强制执行条件唯一性.如果我想创建一个支持逻辑删除的表,但确保COL1对所有未删除的行都是唯一的

SQL> ed
Wrote file afiedt.buf

  1  CREATE TABLE t (
  2    col1 number,
  3    deleted_flag varchar2(1) check( deleted_flag in ('Y','N') )
  4* )
SQL> /

Table created.

SQL> create unique index idx_non_deleted
  2      on t( case when deleted_flag = 'N' then col1 else null end);

Index created.

SQL> insert into t values( 1, 'N' );

1 row created.

SQL> insert into t values( 1, 'N' );
insert into t values( 1, 'N' )
*
ERROR at line 1:
ORA-00001: unique constraint (SCOTT.IDX_NON_DELETED) violated


SQL> insert into t values( 1, 'Y' );

1 row created.

SQL> insert into t values( 1, 'Y' );

1 row created.
Run Code Online (Sandbox Code Playgroud)

但是,如果我们谈论的是一个直接的,基于非函数的直接索引,那么创建索引而不是创建约束真的更有意义的情况可能相对较少.另一方面,在实践中有很大差异的情况相对较少.您几乎从不想要声明引用唯一约束而不是主键约束的外键约束,因此您很少通过仅创建索引而不创建约束来丢失某些内容.


Rog*_*ith 6

正如其他答案中已经解释的那样:约束和索引是不同的实体。但他们缺乏对该主题的准确定义和官方评论。在我们讨论这两个实体之间的关系之前,让我们先看看它们彼此独立的目的。

约束1的目的:

使用约束来定义完整性约束——限制数据库中的值的规则。

索引2的用途:

您可以在列上创建索引以加快查询速度。对于返回一小部分表行的操作,索引可以更快地访问数据。

一般来说,在以下任一情况下,您应该在列上创建索引:

  • 该列经常被查询。
  • 列上存在参照完整性约束。
  • 该列上存在 UNIQUE 键完整性约束。

现在我们知道了什么是约束和索引,但是它们之间的关系是什么?

索引和约束之间的关系为3

  • 约束可能会创建索引或使用现有索引来有效地强制执行自身。例如,PRIMARY KEY 约束将创建一个索引(取决于唯一或非唯一),或者它将找到现有的合适索引并使用它。

  • 索引与约束无关。索引就是索引。

因此,约束可能会创建/使用和索引。索引就是索引,不多也不少。

因此总结一下并直接回答您问题中的以下句子:

但是,我不明白没有约束的唯一索引的原因。

索引加速查询和完整性检查(约束)。此外,对于条件唯一性,使用唯一(功能)索引,因为这无法通过约束来实现。

希望这能为整个主题带来更多的澄清,但原始问题的一个方面仍未得到解答:

为什么在不存在约束的情况下会出现以下错误:

ORA-00001: 违反唯一约束 (TEST.IDX_TEST22)

答案很简单:没有约束,并且错误消息将其命名错误

同一问题参见官方“Oracle Ask TOM”评论4 :

这不是一个限制。错误消息“错误命名”了它。
如果它是一个约束,您可以为其创建一个外键——但您不能。

希望能帮助到你。

链接:

1 Oracle 10g 约束文档

2 关于选择索引策略的 Oracle 10g 文档

3 4 “Oracle Ask TOM”类似问题的解答