将数据库代码发布到非开发数据库时,我使用这种方法 - 我创建了一个sqlplus脚本,它在一个序列中运行多个create table / view / sequence / package / etc语句。我还应该创建回滚脚本,如果在部署或进一步使用期间需要执行drop和其他语句。但总是手动创建回滚脚本非常烦人。 I.E. - 当我把
alter table table_a add column some_column number(5);
进入发布脚本。我必须把
alter table table_a drop column some_column;
进入回滚脚本。反之亦然。
有优化(或半优化)方法吗?也许有些Java / Python / etc库允许将ddl语句解析为逻辑部分?
也许有更好的方法来发布/回滚pl / sql代码?
答案 0 :(得分:3)
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
或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
关于这些结果的一些注意事项:
RESTART START WITH
语法非常有用。您不需要删除或重新创建索引,也不需要多次使用increment by
。此语法不在12c manual中。事实上,我无法在谷歌的任何地方找到它。看起来这个包正在使用未记录的功能。其他一些说明:
可以完全自动化此过程。但基于上述问题以及我使用所有此类自动化工具的经验,您不应该100%信任它。