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

Vincoli multipli nella tabella:come ottenere tutte le violazioni?

Non esiste un modo semplice per segnalare tutte le possibili violazioni dei vincoli. Perché quando Oracle inciampa nella prima violazione di un vincolo, non è possibile un'ulteriore valutazione, l'istruzione fallisce, a meno che quel vincolo non venga differito o gli log errors clausola è stata inclusa nell'istruzione DML. Ma va notato che log errors La clausola non sarà in grado di rilevare tutte le possibili violazioni dei vincoli, registra solo la prima.

Poiché uno dei modi possibili è:

  1. crea exceptions tavolo. Può essere fatto eseguendo ora_home/rdbms/admin/utlexpt.sql sceneggiatura. La struttura della tabella è piuttosto semplice;
  2. disabilita tutti i vincoli di tabella;
  3. esegui DML;
  4. abilita tutti i vincoli con exceptions into <<exception table name>> clausola. Se hai eseguito utlexpt.sql script, il nome delle eccezioni della tabella che verranno archiviate sarebbe exceptions .

Tabella di prova:

create table t1(
  col1 number not null,
  col2 number not null,
  col3 number not null,
  col4 number not null
);

Prova a eseguire un insert dichiarazione:

insert into t1(col1, col2, col3, col4)
  values(1, null, 2, null);

Error report -
SQL Error: ORA-01400: cannot insert NULL into ("HR"."T1"."COL2")

Disabilita tutti i vincoli della tabella:

alter table T1 disable constraint SYS_C009951;     
alter table T1 disable constraint SYS_C009950;     
alter table T1 disable constraint SYS_C009953;     
alter table T1 disable constraint SYS_C009952; 

Prova a eseguire insert precedentemente non riuscito affermazione ancora:

insert into t1(col1, col2, col3, col4)
  values(1, null, 2, null);

1 rows inserted.

commit;

Ora, abilita i vincoli della tabella e memorizza le eccezioni, se presenti, nelle exceptions tabella:

alter table T1 enable constraint SYS_C009951 exceptions into exceptions; 
alter table T1 enable constraint SYS_C009950 exceptions into exceptions; 
alter table T1 enable constraint SYS_C009953 exceptions into exceptions; 
alter table T1 enable constraint SYS_C009952 exceptions into exceptions; 

Controlla le exceptions tabella:

column row_id     format a30;
column owner      format a7;
column table_name format a10;
column constraint format a12;

select *
  from exceptions 

ROW_ID                         OWNER   TABLE_NAME CONSTRAINT 
------------------------------ ------- -------    ------------
AAAWmUAAJAAAF6WAAA             HR      T1         SYS_C009951  
AAAWmUAAJAAAF6WAAA             HR      T1         SYS_C009953

Sono stati violati due vincoli. Per scoprire i nomi delle colonne, fai semplicemente riferimento a user_cons_columns vista dizionario dati:

column table_name   format a10;
column column_name  format a7;
column row_id       format a20;

select e.table_name
     , t.COLUMN_NAME
     , e.ROW_ID
  from user_cons_columns t
  join exceptions e
    on (e.constraint = t.constraint_name)


TABLE_NAME COLUMN_NAME ROW_ID             
---------- ----------  --------------------
T1         COL2        AAAWmUAAJAAAF6WAAA   
T1         COL4        AAAWmUAAJAAAF6WAAA

La query precedente ci fornisce i nomi delle colonne e le righe dei record problematici. Avendo rowid a portata di mano, non dovrebbero esserci problemi nel trovare quei record che causano la violazione dei vincoli, risolverli e riattivarli ancora una volta.

Ecco lo script che è stato utilizzato per generare alter table istruzioni per abilitare e disabilitare i vincoli:

column cons_disable format a50
column cons_enable format a72

select 'alter table ' || t.table_name || ' disable constraint '|| 
        t.constraint_name || ';' as cons_disable
     , 'alter table ' || t.table_name || ' enable constraint '|| 
        t.constraint_name || ' exceptions into exceptions;' as cons_enable
  from user_constraints t
where t.table_name = 'T1'
order by t.constraint_type