Иногда бывает нужно удалить запись, но срабатывает констрейнт о том что есть подчиненные записи. И эта иерархия может быть очень длинная. Конечно, при использовании форенкеев с каскадным удалением, такой проблемы не возникает, но что если используются обычные форенкеи. Для решения данной проблемы, можно использовать следующий скрипт:
create
table list_of_constraints as
select
ddl_constraint
, substr(replace(ddl_constraint, ' ADD ', ' DROP '), 1, instr(ddl_constraint, '
FOREIGN KEY ')) as drop_constraint
, replace(ddl_constraint, ' ENABLE', ' ON DELETE CASCADE ENABLE') as
cascade_constraint
from
(select lpad(' ', 2*(level-1)) || table_name as table_name
, id
, parent_id
, constraint_name
, delete_rule
, r_constraint_name
, decode(constraint_type, 'R', dbms_metadata.get_ddl('REF_CONSTRAINT',
constraint_name)) ddl_constraint
from (select case
when constraint_type = 'R' then (select constraint_name
from
user_constraints urco
where urco.table_name = urcs.table_name
and urco.constraint_type = 'P')
else urcs.constraint_name
end as id
, urcs.r_constraint_name as parent_id
, urcs.table_name
, urcs.constraint_type
, urcs.constraint_name
, urcs.r_constraint_name
, urcs.delete_rule
from user_constraints urcs
where constraint_type in ('P', 'U', 'R')) obtr
connect by nocycle prior obtr.id = obtr.parent_id
start with obtr.table_name = 'AAAA'
and obtr.constraint_type in ('P'))
where
ddl_constraint is not null
and
delete_rule = 'NO ACTION'
/
---
begin
for
r in (select drop_constraint, cascade_constraint from list_of_constraints)
loop
execute immediate r.drop_constraint;
execute immediate r.cascade_constraint;
end
loop;
end;
/
--- DELETE
---------------------------------------------------------------------
delete from
AAAA where name = 'bbbb'
/
--------------------------------------------------------------------------------
---
begin
for
r in (select drop_constraint, ddl_constraint from list_of_constraints)
loop
execute immediate r.drop_constraint;
execute immediate r.ddl_constraint;
end
loop;
end;
/
drop table
list_of_constraints
/
В этом скрипте, мы вычисляем все подчиненные таблицы для таблице АААА. При этом во временную таблицу list_of_constraints мы записываем скрипты для пересоздания уже существующих форенкеев на форенкеи с каскадным удалением.
После пересоздания форенкеев, мы удаляем запись из таблицы АААА и потом восстанавливаем первоначальное состояние форенкеев.
Комментариев нет:
Отправить комментарий