Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Várias restrições na tabela:como obter todas as violações?


Não há uma maneira direta de relatar todas as possíveis violações de restrição. Porque quando o Oracle tropeça na primeira violação de uma restrição, nenhuma avaliação adicional é possível, a instrução falha, a menos que essa restrição seja adiada ou os log errors cláusula foi incluída na instrução DML. Mas deve-se notar que log errors cláusula não será capaz de capturar todas as possíveis violações de restrição, apenas registra a primeira.

Como uma das formas possíveis é:
  1. criar exceptions tabela. Isso pode ser feito executando ora_home/rdbms/admin/utlexpt.sql roteiro. A estrutura da tabela é bem simples;
  2. desabilite todas as restrições de tabela;
  3. executar DMLs;
  4. habilite todas as restrições com exceptions into <<exception table name>> cláusula. Se você executou utlexpt.sql script, o nome das exceções de tabela que serão armazenadas seria exceptions .

Tabela de teste:
create table t1(
  col1 number not null,
  col2 number not null,
  col3 number not null,
  col4 number not null
);

Tente executar um insert demonstração:
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")

Desabilite todas as restrições da tabela:
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; 

Tente executar o insert que falhou anteriormente declaração novamente:
insert into t1(col1, col2, col3, col4)
  values(1, null, 2, null);

1 rows inserted.

commit;

Agora, habilite as restrições da tabela e armazene as exceções, se houver, nas exceptions tabela:
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; 

Verifique as exceptions tabela:
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

Duas restrições foram violadas. Para descobrir os nomes das colunas, basta consultar user_cons_columns visualização do dicionário de dados:
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

A consulta acima nos fornece nomes de colunas e rowids de registros problemáticos. Tendo rowids em mãos, não deve haver problemas para encontrar os registros que causam violação de restrição, corrigi-los e reativar restrições novamente.

Aqui está o script que foi usado para gerar alter table instruções para habilitar e desabilitar restrições:
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