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 elincrement 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%.