4

将数据库代码发布到非开发数据库时,我使用这种方法 - 我创建发布 sqlplus 脚本,该脚本按顺序运行多个 create table/view/sequence/package/etc 语句。如果在部署或进一步使用期间需要,我还应该创建执行 drop 和其他语句的回滚脚本。但是手动创建回滚脚本总是很烦人。IE - 当我把

alter table table_a add column some_column number(5);

进入发布脚本。我必须把

alter table table_a drop column some_column;

进入回滚脚本。反之亦然。

有没有办法优化(或半优化)它?也许有一些 Java/Python/etc 库允许将 ddl 语句解析为逻辑部分?

也许有一些更好的方法来发布/回滚 pl/sql 代码?

4

1 回答 1

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 不适用于CREATEor 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% 相信它。

于 2013-10-25T18:09:53.147 回答