Oracle 重建表(rename)注意事项总结

前一段时间,有一个DBA朋友在完成重建表(rename)工作后,第二天早上业务无法正常运行,出现数据无法插入的限制和错误,后来分析才发现,错误的原因是使用rename方式重建表以后,其它引用这个表的外键约束指向没有重新定义到这个重建的新表中,从而导致这些表在插入新数据时,违反数据完整性约束,导致数据无法正常插入。影响了业务大概有1个多小时,真是一次血淋淋的教训啊。

使用rename方式重建表是我们日常DBA维护工作中经常使用的一种方法,因为CTAS+rename这种配合方式,非常实用和高效。很多DBA朋友应该也都是用过rename方式重建表,而且重建完成以后也都一切正常,没有引起过问题。但是,我想说的是,使用rename重建表后,具体需要完成哪些扫尾工作你真的清楚吗??

这篇文章主要就是归纳当我们使用rename方式重建表后,需要进行哪些扫尾工作,如果你还不是很清楚,一定要仔细阅读这篇文章,同时在以后的重建表工作中矫正过来,否则,问题迟早有一天会降临到你的身边!

 

二、重建表的方式

这里先不谈其它,仅仅说一下重建表的方法。如下

1、为了确保所有表字段、字段类型、长度完全一样,我一般不建议使用CTAS方式来重建表。

2、一般我都是使用下面两种方法中的一个,来抽取表的定义

select dbms_metadata.get_ddl('TABLE',upper('&i_table_name'),upper('&i_owner')) from dual;

使用PL/SQL developer类似这样的工具,来查看表定义语句

3、重新建一张_old类型的表(根据上面的抽取的表定义),然后使用insert /*+ append */ xx select xxx 方式完成数据的转换

4、最后使用rename方式倒换这两张表的名字

 

 

三、重建表注意事项

索引重建:这里最关键的是,重建后索引的名字是否必须和以前的一样,如果需要一样,则必须将当前使用的索引名字先rename,否则创建的时候会出现索引名字已经存在的错误,如下:

select 'alter index ' || owner || '.' || index_name || ' rename to ' ||

substr(index_name, 1, 26) || '_old;'

from dba_indexes a

where a.table_owner = 'DBMON'

AND A.table_name = 'DH_T';

依赖对象重建:一般可以使用如下方式完成

select 'alter '||decode(type,'PACKAGE BODY','PACKAGE',type)||' '||owner||'.'||name||' compile;'

from dba_dependencies a

where a.referenced_name = 'DH_T'

and a.referenced_owner = 'DBMON';

注意:

1、这里重建的只是直接依赖对象,必须考虑那些间接依赖的对象(例如 view1依赖A表,view2依赖view1),查找方法和上面差不多

2、如果这些依赖对象中存在一些私有对象(例如dblink等),我们用DBA用户重新编译是会出现编译错误,对于这种对象,必须以对应对象的所属者才能编译成功。(也可用用10g以后新出现的代理权限来完成这类任务!)

针对PL/SQL代码(包、函数、过程等),是否存在私有对象的查找方法,如下:

select *

from dba_source a

where (a.owner, a.name) in

(select owner, name

from dba_dependencies b

where b.referenced_name = 'DH_T'

and b.referenced_owner = 'DBMON')

and a.TEXT like '%@%';

针对视图中是否存在私有对象的查找方法,如下(由于是long类型,必须得一个一个查看):

select *

from dba_views a

where (a.owner, a.view_name) in

(select owner, name

from dba_dependencies b

where b.referenced_name = 'DH_T'

and b.referenced_owner = 'DBMON'

and b.type = 'VIEW')

权限重建:可以使用如下语句

select 'grant ' || PRIVILEGE || ' on ' || owner || '.' || table_name ||

' to ' || grantee || ';'

from dba_tab_privs

where table_name = upper('&i_table_name')

and owner = upper('&i_owner');

 

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/ebee75ca012a16138956439de0713d97.html