【问题标题】:Oracle unique constraint and unique indexOracle 唯一约束和唯一索引
【发布时间】:2011-11-23 05:21:15
【问题描述】:

有人能澄清一下没有唯一约束的唯一索引(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

到目前为止,似乎存在一个约束。但是

create table test33(id int not null primary key, 
test22_id int not null, 
foreign key(test22_id) references test22(id) );

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

有很多文章解释了为什么可以有一个没有唯一索引的唯一约束;这很清楚,而且很有意义。但是,我不明白没有约束的唯一索引的原因。

【问题讨论】:

    标签: oracle unique-key


    【解决方案1】:

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

    约束1的目的:

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

    索引的用途2

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

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

    • 该列被频繁查询。
    • 列上存在参照完整性约束。
    • 列上存在唯一键完整性约束。

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

    索引和约束的关系是3

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

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

    所以,一个约束可能会创建/使用和索引。 INDEX 就是 INDEX,不多也不少。

    所以总结一下,直接从你的问题中解决以下句子:

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

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

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

    为什么不存在约束时会出现如下错误:

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

    答案很简单:没有约束和错误信息misnames吧!

    查看官方“Oracle Ask TOM”评论4关于同样的问题:

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

    希望对你有帮助。

    链接:

    1Oracle 10g Documentation on Constraints

    2Oracle 10g Documentation on Selecting an Index Strategy

    34"Oracle Ask TOM" answer to a similar problem

    【讨论】:

      【解决方案2】:

      你不能通过声明一个唯一约束来实现条件唯一性,但是你可以通过声明一个唯一索引来做到这一点。

      如果你尝试在下面执行,请支持:

      alter table test22 
      add constraint test22_u 
      unique (id, case when tmp = 'aaa' then null else tmp end);
      
      ORA-00904: : invalid identifier 
      

      但是如果你可以通过使用唯一索引来做到这一点

      create unique index test22_u 
      on test22 ( customer_id, 
      case when is_default = 'Y' then null else address_id end)
      

      【讨论】:

        【解决方案3】:

        在这种情况下可能有用的另一点是: 禁用/删除现有的唯一约束不会删除基础唯一索引。您必须明确删除唯一索引。

        【讨论】:

        • 这是不正确的(至少对于 10g)。实际上,您必须在删除唯一约束以保留索引时指定 KEEP INDEX。此外,索引不必是唯一的。
        • 有趣。但是,从 11g 开始就不是这样了。
        【解决方案4】:

        约束和索引是独立的逻辑实体。例如,唯一约束在 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.
        

        但是,如果我们谈论的是直接唯一的非基于函数的索引,那么创建索引而不是创建约束确实更有意义的情况可能相对较少。另一方面,它在实践中产生很大差异的情况相对较少。您几乎从不想声明引用唯一约束而不是主键约束的外键约束,因此您很少会因为只创建索引而不创建约束而丢失某些东西。

        【讨论】:

        • 感谢您的回答,现在越来越清楚了。我真正不喜欢的是两种情况下的错误代码相同(ORA-00001),带有约束和唯一索引。
        • 非常好,感谢您对是否可以对唯一 FBI 创建唯一约束的“最终决定权”。
        • 谢谢 - 这是我发现的两者之间区别的唯一清晰解释。我看到有人提到声明唯一约束为优化器提供了比唯一索引更多的信息……这是真的吗,这是否意味着唯一约束可以在没有约束的情况下比唯一索引提供一些性能优势?
        猜你喜欢
        • 1970-01-01
        • 2014-07-18
        • 1970-01-01
        • 2021-11-02
        • 2015-12-29
        • 2011-03-18
        • 2023-03-11
        • 2018-12-02
        • 1970-01-01
        相关资源
        最近更新 更多