2010-03-03 22 views
13

ho avuto un vincolo in una tabellaTrovare vincolo fantasma da Oracle DB


CREATE TABLE "USERSAPPLICATIONS" (
    "USERID" NUMBER NOT NULL , 
    "APPLICATIONNAME" VARCHAR2 (30) NOT NULL , 
CONSTRAINT "PK_USERSAPPLICATIONS" PRIMARY KEY ("USERID","APPLICATIONNAME") 
) 
/

Due settimane fa ho modificato il tavolo, ha aggiunto alcune colonne, cancellato le "PK_USERSAPPLICATIONS" vincolo e ha aggiunto una chiave surrogata. Posso vedere in Oracle SQL Developer che il vincolo PK_USERSAPPLICATIONS non esiste più.

Indipendentemente da questo, quando provo ad aggiungere due voci con la stessa combinazione userid/applicationName, ottengo un errore


SQL Error: ORA-00001: unique constraint (ACCOUNTMP1.PK_USERSAPPLICATIONS) violated 
00001. 00000 - "unique constraint (%s.%s) violated" 
*Cause: An UPDATE or INSERT statement attempted to insert a duplicate key. 
      For Trusted Oracle configured in DBMS MAC mode, you may see 
      this message if a duplicate entry exists at a different level. 
*Action: Either remove the unique restriction or do not insert the key. 

Quando eseguo la dichiarazione


SELECT * 
FROM user_cons_columns 
WHERE constraint_name = 'PK_USERSAPPLICATIONS' 

ottengo zero righe . Come può essere? Oracle non dovrebbe avere alcuna conoscenza del vincolo PK_USERSAPPLICATIONS come è stato cancellato già settimane fa, e non posso vederlo neanche nel database.

risposta

30

Hai ancora l'indice utilizzato da quel vincolo? Perché se non hai incluso la clausola DROP INDEX quando hai eliminato il vincolo, sarà ancora presente. Inizia con

SELECT * 
FROM user_indexes 
WHERE index_name = 'PK_USERSAPPLICATIONS' 
/

In alternativa,

select index_name 
from user_indexes 
where table_name = 'USERSAPPLICATIONS' 
and uniqueness='UNIQUE' 
/

o

select index_name 
from user_ind_columns 
where table_name = 'USERSAPPLICATIONS' 
and column_name in ('USERID' ,'APPLICATIONNAME') 
/

modificare

Proof of concept

SQL> create table t23 (id number not null, alt_key varchar2(10) not null) 
    2/

Table created. 

SQL> create unique index t23_idx on t23 (id) 
    2/

Index created. 

SQL> alter table t23 add constraint t23_pk primary key (id) using index 
    2/

Table altered. 

SQL> insert into t23 values (1, 'SAM I AM') 
    2/

1 row created. 

SQL> insert into t23 values (1, 'MR KNOX') 
    2/
insert into t23 values (1, 'MR KNOX') 
* 
ERROR at line 1: 
ORA-00001: unique constraint (APC.T23_PK) violated 

SQL> 

Quindi il vincolo funziona. Cosa succede se lo rilasciamo, senza la clausola DROP INDEX?

SQL> alter table t23 drop constraint t23_pk 
    2/

Table altered. 

SQL> insert into t23 values (1, 'MR KNOX') 
    2/
insert into t23 values (1, 'MR KNOX') 
* 
ERROR at line 1: 
ORA-00001: unique constraint (APC.T23_IDX) violated 


SQL> 

Notare il sottile cambiamento nel messaggio di errore. Il secondo errore fa riferimento al nome dell'indice, mentre il messaggio originale faceva riferimento al vincolo. Se il nome dell'indice è uguale al nome del vincolo, sarebbe difficile da diagnosticare.

Se non si precompila in modo esplicito l'indice univoco, il comportamento predefinito di Oracle è quello di creare un indice non univoco. Di conseguenza, l'eliminazione del vincolo senza rilasciare l'indice non causa questo problema. (Si noti che questo comportamento è vero per 11 g. Presumo - ma non posso essere sicuro - che sia anche in questo modo nelle versioni precedenti).

+0

+1. Spot on. Non ho mai pensato in questo modo. – Guru

+0

Risposta molto buona e completa. Era così - stupidamente l'indice era chiamato esattamente come il vincolo nel mio caso. – simon

+0

Grazie. Dopo aver trovato l'indice, lo rilasciamo usando un altro script DROP INDEX PK_USERSAPPLICATIONS; – Coisox

1

Prova a verificare l'indice per queste colonne. In alcuni casi l'indice associato al vincolo non viene eliminato dopo la cancellazione dei vincoli

Problemi correlati