Есть более простой способ создать нужные сценарии, используя системные таблицы user_tables и user_constraints для динамического создания DDL. Недостатком является то, что это требует простоя. Также обратите внимание, что я использую команду truncate. чем delete, что должно быть быстрее.
Предполагая простую таблицу, которая выглядит так:
create table a (
foo number(10)
, bar number(10)
, constraint pk_a primary key (foo)
, constraint fk_a foreign key ( bar ) references a(foo )
);
Этот непривлекательный запрос
select cmd
from (
select table_name
, 1 as stage -- Just used to order by at the end.
, 'create table ' || table_name || '_backup as select * from '
|| table_name || ';' || chr(10) as cmd
-- chr(10) is LF
from user_tab_columns -- View of all columns
where column_name = 'FOO'
and data_precision = 10 -- Length of the number
union all
select table_name
, 3 as stage
, 'truncate table ' || table_name || ';' || chr(10) -- Remove all data
|| 'alter table ' || table_name
|| ' modify ( foo number(3));' || chr(10)
|| 'insert into ' || table_name || ' select * from '
|| table_name || '_backup;' || chr(10)
|| 'drop table ' || table_name || '_backup;' as cmd
from user_tab_columns
where column_name = 'FOO'
and data_precision = 10
union all
select ut.table_name
, 2 as stage
-- Disable the constraint
, 'alter table ' || uc.table_name || ' disable constraint '
|| uc.constraint_name || ';' || chr(10) as cmd
from user_constraints uc -- All named constraints
join user_tab_columns ut
on uc.table_name = ut.table_name
where ut.column_name = 'FOO'
and ut.data_precision = 10
and constraint_type = 'R' -- Foreign Key constraints (see link)
union all
select ut.table_name
, 4 as stage
, 'alter table ' || uc.table_name || ' enable constraint '
|| uc.constraint_name || ';' || chr(10) as cmd
from user_constraints uc
join user_tab_columns ut
on uc.table_name = ut.table_name
where ut.column_name = 'FOO'
and ut.data_precision = 10
and constraint_type = 'R'
)
order by stage
Произведет следующее:
create table A_backup as select * from A; -- Create your backup
alter table A disable constraint FK_A; -- Disable FKs
truncate table A; -- Remove all data in the table
alter table A modify ( foo number(3)); -- Reduce the size of the column
insert into A select * from A_backup; -- Replace all the data
drop table A_backup; -- Drop the backup
alter table A enable constraint FK_A; -- Re-enable FKs
Из-за столбца stage это будет выполняться не таблица за таблицей, а поэтапно, так что все ограничения будут отключены одновременно, что позволит избежать проблем. Если вы боитесь (я бы испугался), удалите drop из _backup таблиц из запроса; это означает, что что бы ни пошло не так, вы в безопасности.
Если вы запускаете это в SQL*Plus, вы также хотите включить whenever sqlerror exit, чтобы в случае возникновения проблемы, например, отсутствия больше табличного пространства, вы не усекали то, для чего у вас нет резервной копии. Возможно, стоит запускать его поэтапно, чтобы вы знали, что все выполнено правильно.
Я бы предложил протестировать это на другом пользователе с несколькими таблицами, чтобы убедиться, что он делает все, что вам нужно.
person
Ben
schedule
05.09.2012