Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

automatizando o oráculo de script de reversão


DBMS_METADATA_DIFF e algumas consultas de metadados podem automatizar esse processo.

Este exemplo demonstra 6 tipos de alterações:1) adicionar uma coluna 2) incrementar uma sequência 3) eliminar uma tabela 4) criar uma tabela 5) alterar uma visualização 6) alocar uma extensão.
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;

Você está correto que DBMS_METADATA_DIFF não funciona para CREATE ou DROP . Tentar diferenciar um objeto que existe apenas em um esquema gerará uma mensagem de erro como esta:
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

No entanto, soltar e adicionar objetos pode ser fácil de script com o seguinte:
--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" 

As alterações podem ser tratadas com uma instrução SQL como esta:
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

Algumas notas sobre esses resultados:
  • ADD_COLUMN funciona conforme o esperado.
  • ALLOCATE_EXTENT provavelmente é um falso positivo. Duvido que você se importe com a criação de segmento adiado. É muito improvável que afete seu sistema.
  • CHANGE_VIEW não funciona. Mas, como nas consultas de metadados anteriores, deve haver uma maneira relativamente fácil de criar esse script usando DBA_VIEWS.
  • INCREMENT_SEQUENCE funciona muito bem. Na maioria das vezes, um aplicativo não se preocupa com os valores da sequência. Mas às vezes, quando as coisas ficam fora de sincronia, você precisa alterá-las. Este RESTART START WITH sintaxe pode ser muito útil. Você não precisa descartar ou recriar os índices, ou mexer com o increment by várias vezes. Esta sintaxe não está no manual 12c. Na verdade, não consigo encontrá-lo em nenhum lugar no Google. Parece que este pacote está usando recursos não documentados.

Algumas outras notas:
  • O pacote pode ser muito lento às vezes.
  • Se os links de rede no servidor forem um problema, você precisará executá-lo por meio de uma instância local com links para ambos os servidores.
  • Pode haver falsos positivos. Às vezes, ele retorna uma linha com apenas um espaço.

É possível automatizar totalmente esse processo. Mas com base nos problemas acima e em minha experiência com todos tais ferramentas automatizadas, você não deve confiar 100%.