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 é:
- criar
exceptions
tabela. Isso pode ser feito executandoora_home/rdbms/admin/utlexpt.sql
roteiro. A estrutura da tabela é bem simples; - desabilite todas as restrições de tabela;
- executar DMLs;
- habilite todas as restrições com
exceptions into <<exception table name>>
cláusula. Se você executouutlexpt.sql
script, o nome das exceções de tabela que serão armazenadas seriaexceptions
.
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