自动化回滚脚本oracle

时间:2013-10-24 19:33:58

标签: oracle plsql release-management

将数据库代码发布到非开发数据库时,我使用这种方法 - 我创建了一个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代码?

1 个答案:

答案 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不适用于CREATEDROP。尝试区分仅存在于一个模式中的对象将生成错误消息 像这样:

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 manual中。事实上,我无法在谷歌的任何地方找到它。看起来这个包正在使用未记录的功能。

其他一些说明:

  • 有时包裹可能很慢。
  • 如果服务器上的网络链接出现问题,您需要通过本地实例运行它,并指向两台服务器的链接。
  • 可能存在误报。有时它返回一行只有一个空格。

可以完全自动化此过程。但基于上述问题以及我使用所有此类自动化工具的经验,您不应该100%信任它。