Oracle
 sql >> Base de données >  >> RDS >> Oracle

Contraintes multiples dans le tableau :comment obtenir toutes les violations ?

Il n'existe aucun moyen simple de signaler toutes les violations de contraintes possibles. Parce que lorsque Oracle tombe sur la première violation d'une contrainte, aucune autre évaluation n'est possible, l'instruction échoue, à moins que cette contrainte ne soit différée ou que les log errors clause a été incluse dans l'instruction DML. Mais il convient de noter que log errors La clause ne pourra pas intercepter toutes les violations de contrainte possibles, enregistre simplement la première.

Comme l'un des moyens possibles est de :

  1. créer des exceptions table. Cela peut être fait en exécutant ora_home/rdbms/admin/utlexpt.sql scénario. La structure du tableau est assez simple ;
  2. désactiver toutes les contraintes de table ;
  3. exécuter les DML ;
  4. activer toutes les contraintes avec exceptions into <<exception table name>> clause. Si vous avez exécuté utlexpt.sql script, le nom des exceptions de table qui vont être stockées serait exceptions .

Tableau des tests :

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

Essayez d'exécuter un insert déclaration :

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")

Désactiver toutes les contraintes de la table :

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; 

Essayez d'exécuter le insert précédemment échoué déclaration à nouveau :

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

1 rows inserted.

commit;

Maintenant, activez les contraintes de la table et stockez les exceptions, s'il y en a, dans les exceptions tableau :

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; 

Vérifiez les exceptions tableau :

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

Deux contraintes ont été violées. Pour connaître les noms des colonnes, reportez-vous simplement à user_cons_columns vue dictionnaire de données :

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 requête ci-dessus nous donne les noms de colonne et les rowids des enregistrements problématiques. Ayant des rowids à portée de main, il ne devrait y avoir aucun problème pour trouver les enregistrements qui causent une violation de contrainte, les corriger et réactiver les contraintes une fois de plus.

Voici le script qui a été utilisé pour générer alter table instructions d'activation et de désactivation des contraintes :

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