DBMS_METADATA_DIFF e alcune query di metadati possono automatizzare questo processo.
Questo esempio mostra 6 tipi di modifiche:1) aggiunta di una colonna 2) incremento di una sequenza 3) eliminazione di una tabella 4) creazione di una tabella 5) modifica di una vista 6) allocazione di un'estensione.
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;
Hai ragione sul fatto che DBMS_METADATA_DIFF non funziona per CREATE
o DROP
. Il tentativo di differenziare un oggetto che esiste solo in uno schema genererà un messaggio di errore come questo:
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
Tuttavia, l'eliminazione e l'aggiunta di oggetti può essere facile da scrivere con quanto segue:
--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"
Gli alter possono essere gestiti con un'istruzione SQL come questa:
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
Alcune note su questi risultati:
- ADD_COLUMN funziona come previsto.
- ALLOCATE_EXTENT è probabilmente un falso positivo, dubito che ti interessi la creazione di segmenti posticipati. È molto improbabile che influisca sul tuo sistema.
- CHANGE_VIEW non funziona affatto. Ma come per le precedenti query sui metadati, dovrebbe esserci un modo relativamente semplice per creare questo script utilizzando DBA_VIEWS.
- INCREMENT_SEQUENCE funziona troppo bene. La maggior parte delle volte un'applicazione non si preoccupa dei valori di sequenza. Ma a volte, quando le cose non sono sincronizzate, devi cambiarle. Questo
RESTART START WITH
la sintassi può essere molto utile. Non è necessario eliminare o ricreare gli indici o pasticciare con l'increment by
più volte. Questa sintassi non è nel manuale 12c. In effetti, non riesco a trovarlo da nessuna parte su Google. Sembra che questo pacchetto utilizzi funzionalità non documentate.
Qualche altra nota:
- Il pacchetto a volte può essere molto lento.
- Se i collegamenti di rete sul server sono un problema, dovrai eseguirlo tramite un'istanza locale con collegamenti a entrambi i server.
- Potrebbero esserci falsi positivi. A volte restituisce una riga con solo uno spazio.
È possibile automatizzare completamente questo processo. Ma sulla base dei problemi precedenti e della mia esperienza con tutti tali strumenti automatizzati, non dovresti fidarti al 100%.