有生成所需的腳本更簡單的方法,使用系統表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
,這韓元不是一個一個地一桌一桌地做,而是一步一步地做,以便所有的限制都會消失同時能夠避免問題。如果你害怕(我會),然後從查詢中刪除_backup
表中的drop
;這意味着無論什麼錯誤,你都是安全的。
如果您在SQL * Plus中運行此操作,則還需要包含whenever sqlerror exit
,這樣如果出現問題(例如沒有更多的表空間),則不會截斷未備份的內容。它可能幾乎值得逐步運行它,以便你知道一切都已正確完成。
我建議在不同的用戶上測試這個表格,以確保它滿足您的一切需求。
來源
2012-09-05 12:02:11
Ben
謝謝!你能否給上面的_「看起來不看上去的」_代碼添加註釋。我不想運行我不完全理解的DDL查詢。 – gdoron
我試圖讓它更容易理解......並添加了一些警告提示:) – Ben
謝謝我非常感謝您的幫助和努力。最後一件事,'chr(10)'做了什麼?我從來沒有在查詢中看到過這樣的事情。 – gdoron