Уникальное ограничение Oracle и уникальный индекс

может ли кто-нибудь уточнить, какова цель наличия уникального индекса без уникального ограничения (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

пока похоже, что есть ограничение. Но!--4-->

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". Я совершенно сбит с толку этим поведением. Есть ограничение или нет?

есть много статей, которые объясняют, почему возможно иметь уникальное ограничение без уникального индекса; это ясно и имеет смысл. Однако Я не понимаю причину уникального индекса без ограничений.

2 ответов


ограничение и индекс являются отдельными логическими сущностями. Например, уникальное ограничение отображается в USER_CONSTRAINTS (или ALL_CONSTRAINTS или DBA_CONSTRAINTS). Индекс отображается в USER_INDEXES (или ALL_INDEXES или DBA_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.

но если мы говорим о прямом уникальном нефункциональном индексе, то, вероятно, их относительно немного случаи, когда действительно имеет смысл создавать индекс, а не создавать ограничение. С другой стороны, есть относительно мало случаев, когда это имеет большое значение на практике. Вы почти никогда не захотите объявлять ограничение внешнего ключа, которое ссылается на уникальное ограничение, а не на ограничение первичного ключа, поэтому вы редко что-то теряете, только создавая индекс и не создавая ограничение.


еще один момент, который может быть полезным в этом контексте : Отключение / удаление существующего уникального ограничения не удаляет базовый уникальный индекс. Вы должны удалить уникальный индекс явно.