sql >> Base de Datos >  >> RDS >> Oracle

oráculo de automatización de secuencias de comandos de reversión

DBMS_METADATA_DIFF y algunas consultas de metadatos pueden automatizar este proceso.

Este ejemplo demuestra 6 tipos de cambios:1) agregar una columna 2) incrementar una secuencia 3) quitar una tabla 4) crear una tabla 5) cambiar una vista 6) asignar una extensión.

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;

Tiene razón en que DBMS_METADATA_DIFF no funciona para CREATE o DROP . Intentar diferenciar un objeto que solo existe en un esquema generará un mensaje de error como este:

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

Sin embargo, soltar y agregar objetos puede ser fácil de programar con lo siguiente:

--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" 

Los cambios se pueden manejar con una declaración 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

Algunas notas sobre estos resultados:

  • ADD_COLUMN funciona como se esperaba.
  • ALLOCATE_EXTENT es probablemente un falso positivo, dudo que le importe la creación de segmentos diferidos. Es muy poco probable que afecte su sistema.
  • CHANGE_VIEW no funciona en absoluto. Pero al igual que con las consultas de metadatos anteriores, debería haber una manera relativamente fácil de construir este script usando DBA_VIEWS.
  • INCREMENT_SEQUENCE funciona demasiado bien. La mayoría de las veces, una aplicación no se preocupa por los valores de secuencia. Pero a veces, cuando las cosas se desincronizan, es necesario cambiarlas. Este RESTART START WITH La sintaxis puede ser muy útil. No es necesario eliminar o volver a crear los índices, ni alterar el increment by varias veces. Esta sintaxis no está en el manual 12c. De hecho, no puedo encontrarlo en Google. Parece que este paquete está utilizando funciones no documentadas.

Algunas otras notas:

  • El paquete puede ser muy lento a veces.
  • Si los enlaces de red en el servidor son un problema, deberá ejecutarlo a través de una instancia local con enlaces a ambos servidores.
  • Puede haber falsos positivos. A veces devuelve una fila con solo un espacio.

Es posible automatizar completamente este proceso. Pero según los problemas anteriores y mi experiencia con todos tales herramientas automatizadas, no debe confiar en ellas al 100%.