sql >> Base de Datos >  >> RDS >> Oracle

Múltiples restricciones en la tabla:¿Cómo obtener todas las violaciones?

No existe una manera directa de informar todas las posibles violaciones de restricciones. Porque cuando Oracle tropieza con la primera violación de una restricción, no es posible una evaluación adicional, la declaración falla, a menos que esa restricción se difiera uno o los log errors cláusula se ha incluido en la instrucción DML. Pero debe tenerse en cuenta que log errors La cláusula no podrá detectar todas las posibles infracciones de restricciones, solo registra la primera.

Como una de las formas posibles es:

  1. crear exceptions mesa. Se puede hacer ejecutando ora_home/rdbms/admin/utlexpt.sql texto. La estructura de la mesa es bastante simple;
  2. deshabilitar todas las restricciones de la tabla;
  3. ejecutar DML;
  4. habilitar todas las restricciones con exceptions into <<exception table name>> cláusula. Si ejecutó utlexpt.sql script, el nombre de la tabla de excepciones que se van a almacenar sería exceptions .

Tabla de prueba:

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

Intenta ejecutar un insert declaración:

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

Deshabilitar todas las restricciones de la tabla:

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; 

Intente ejecutar el insert fallido anteriormente declaración de nuevo:

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

1 rows inserted.

commit;

Ahora, habilite las restricciones de la tabla y almacene las excepciones, si las hay, en las exceptions tabla:

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; 

Compruebe las exceptions tabla:

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

Se han violado dos restricciones. Para averiguar los nombres de las columnas, simplemente consulte user_cons_columns vista del diccionario de datos:

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 consulta anterior nos proporciona nombres de columna y ID de fila de registros problemáticos. Teniendo los ID de fila a mano, no debería haber ningún problema para encontrar los registros que causan la violación de la restricción, corregirlos y volver a habilitar las restricciones una vez más.

Aquí está la secuencia de comandos que se ha utilizado para generar alter table declaraciones para habilitar y deshabilitar restricciones:

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