DBMS_METADATA_DIFF和一些元数据查询可以自动执行此过程。
此示例演示了 6 种类型的更改:1) 添加列 2) 递增序列 3) 删除表 4) 创建表 5) 更改视图 6) 分配范围。
create table user1.add_column(id number);
create table user2.add_column(id number);
alter table user2.add_column add some_column number(5);
create sequence user1.increment_sequence nocache;
select user1.increment_sequence.nextval from dual;
select user1.increment_sequence.nextval from dual;
create sequence user2.increment_sequence nocache;
select user2.increment_sequence.nextval from dual;
create table user1.drop_table(id number);
create table user2.create_table(id number);
create view user1.change_view as select 1 a from dual;
create view user2.change_view as select 2 a from dual;
create table user1.allocate_extent(id number);
create table user2.allocate_extent(id number);
insert into user2.allocate_extent values(1);
rollback;
您是正确的 DBMS_METADATA_DIFF 不适用于CREATE
or DROP
。尝试区分仅存在于一个模式中的对象将生成如下错误消息:
ORA-31603: object "EXTRA_TABLE" of type TABLE not found in schema "USER1"
ORA-06512: at "SYS.DBMS_METADATA", line 7944
ORA-06512: at "SYS.DBMS_METADATA_DIFF", line 712
但是,删除和添加对象可能很容易使用以下脚本编写:
--Dropped objects
select 'DROP '||object_type||' USER1.'||object_name v_sql
from
(
select object_name, object_type from dba_objects where owner = 'USER1'
minus
select object_name, object_type from dba_objects where owner = 'USER2'
);
V_SQL
-----
DROP TABLE USER1.DROPPED_TABLE
--Added objects
select dbms_metadata.get_ddl(object_type, object_name, 'USER2') v_sql
from
(
select object_name, object_type from dba_objects where owner = 'USER2'
minus
select object_name, object_type from dba_objects where owner = 'USER1'
);
V_SQL
-----
CREATE TABLE "USER2"."CREATED_TABLE"
( "ID" NUMBER
) SEGMENT CREATION DEFERRED
PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
NOCOMPRESS LOGGING
TABLESPACE "USERS"
可以使用如下 SQL 语句来处理变更:
select object_name, object_type, dbms_metadata_diff.compare_alter(
object_type => object_type,
name1 => object_name,
name2 => object_name,
schema1 => 'USER2',
schema2 => 'USER1',
network_link1 => 'MYSELF',
network_link2 => 'MYSELF') difference
from
(
select object_name, object_type from dba_objects where owner = 'USER1'
intersect
select object_name, object_type from dba_objects where owner = 'USER2'
) objects;
OBJECT_NAME OBJECT_TYPE DIFFERENCE
----------- ----------- ----------
ADD_COLUMN TABLE ALTER TABLE "USER2"."ADD_COLUMN" DROP ("SOME_COLUMN")
ALLOCATE_EXTENT TABLE -- ORA-39278: Cannot alter table with segments to segment creation deferred.
CHANGE_VIEW VIEW -- ORA-39308: Cannot alter attribute of view: SUBQUERY
INCREMENT_SEQUENCE SEQUENCE ALTER SEQUENCE "USER2"."INCREMENT_SEQUENCE" RESTART START WITH 3
关于这些结果的一些说明:
- ADD_COLUMN 按预期工作。
- ALLOCATE_EXTENT 可能是误报,我怀疑您是否关心延迟段的创建。它不太可能影响您的系统。
- CHANGE_VIEW 根本不起作用。但与之前的元数据查询一样,应该有一种相对简单的方法来使用 DBA_VIEWS 构建此脚本。
- INCREMENT_SEQUENCE 效果太好了。大多数时候,应用程序并不关心序列值。但有时当事情不同步时,你需要改变它们。这种
RESTART START WITH
语法非常有用。您不需要删除或重新创建索引,也不需要increment by
多次弄乱。此语法不在12c 手册中。事实上,我在谷歌的任何地方都找不到它。看起来这个包正在使用未记录的功能。
其他一些注意事项:
- 包裹有时会很慢。
- 如果服务器上的网络链接有问题,您将需要通过本地实例运行它,并链接到两台服务器。
- 可能存在误报。有时它会返回一行,其中只有一个空格。
这个过程可以完全自动化。但基于上述问题,以及我对所有此类自动化工具的经验,你不应该 100% 相信它。