DBMS_METADATA_DIFF i kilka zapytań o metadane może zautomatyzować ten proces.
Ten przykład ilustruje 6 typów zmian:1) dodanie kolumny 2) zwiększenie sekwencji 3) usunięcie tabeli 4) utworzenie tabeli 5) zmiana widoku 6) przypisanie zakresu.
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;
Masz rację, że DBMS_METADATA_DIFF nie działa dla CREATE
lub DROP
. Próba porównania obiektu, który istnieje tylko w jednym schemacie, wygeneruje komunikat o błędzie podobny do tego:
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
Jednak upuszczanie i dodawanie obiektów może być łatwe do napisania w następujący sposób:
--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"
Zmiany można obsługiwać za pomocą instrukcji SQL w następujący sposób:
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
Kilka uwag na temat tych wyników:
- ADD_COLUMN działa zgodnie z oczekiwaniami.
- ALLOCATE_EXTENT jest prawdopodobnie fałszywym alarmem, wątpię, czy zależy Ci na tworzeniu odroczonego segmentu. Jest bardzo mało prawdopodobne, że wpłynie to na twój system.
- CHANGE_VIEW w ogóle nie działa. Ale podobnie jak w przypadku poprzednich zapytań o metadane, powinien istnieć stosunkowo łatwy sposób na zbudowanie tego skryptu przy użyciu DBA_VIEWS.
- INCREMENT_SEQUENCE działa zbyt dobrze. W większości przypadków aplikacja nie dba o wartości sekwencji. Ale czasami, gdy coś nie jest zsynchronizowane, musisz je zmienić. To
RESTART START WITH
składnia może być bardzo pomocna. Nie musisz usuwać ani ponownie tworzyć indeksów, ani bałaganić zincrement by
wiele razy. Ta składnia nie znajduje się w podręczniku 12c. W rzeczywistości nie mogę go znaleźć nigdzie w Google. Wygląda na to, że ten pakiet używa nieudokumentowanych funkcji.
Kilka innych notatek:
- Pakiet może czasami być bardzo powolny.
- Jeśli łącza sieciowe na serwerze stanowią problem, musisz uruchomić go przez lokalną instancję z łączami do obu serwerów.
- Mogą występować fałszywe alarmy. Czasami zwraca wiersz zawierający tylko spację.
Istnieje możliwość pełnej automatyzacji tego procesu. Ale w oparciu o powyższe problemy i moje doświadczenie ze wszystkimi takich zautomatyzowanych narzędzi, nie powinieneś ufać im w 100%.