Oracle
 sql >> Database >  >> RDS >> Oracle

Vincolo univoco Oracle e indice univoco

Un vincolo e un indice sono entità logiche separate. Un vincolo univoco, ad esempio, è visibile in USER_CONSTRAINTS (o ALL_CONSTRAINTS o DBA_CONSTRAINTS ). Un indice è visibile in USER_INDEXES (o ALL_INDEXES o DBA_INDEXES ).

Un vincolo univoco viene imposto da un indice sebbene sia possibile (e talvolta necessario) applicare un vincolo univoco utilizzando un indice non univoco. Un vincolo univoco differibile, ad esempio, viene applicato utilizzando un indice non univoco. Se crei un indice non univoco su una colonna e successivamente crei un vincolo univoco, puoi anche utilizzare quell'indice non univoco per applicare il vincolo univoco.

In pratica, un indice univoco agisce in modo molto simile a un vincolo univoco non differibile in quanto genera lo stesso errore generato da un vincolo univoco poiché l'implementazione di vincoli univoci utilizza l'indice. Ma non è proprio la stessa cosa perché non c'è alcun vincolo. Quindi, come hai visto, non esiste un vincolo univoco, quindi non puoi creare un vincolo di chiave esterna che faccia riferimento alla colonna.

Ci sono casi in cui è possibile creare un indice univoco che non è possibile creare un vincolo univoco. Un indice basato su funzione, ad esempio, che impone l'univocità condizionale. Se volessi creare una tabella che supportasse le eliminazioni logiche ma assicurati che COL1 è unico per tutte le righe non eliminate

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.

Ma se stiamo parlando di un indice univoco diretto non basato su funzioni, ci sono probabilmente relativamente pochi casi in cui ha davvero più senso creare l'indice piuttosto che creare il vincolo. D'altra parte, ci sono relativamente pochi casi in cui fa molta differenza nella pratica. Non vorresti quasi mai dichiarare un vincolo di chiave esterna che fa riferimento a un vincolo univoco piuttosto che a un vincolo di chiave primaria, quindi raramente perdi qualcosa creando solo l'indice e non creando il vincolo.