sql >> Databasteknik >  >> RDS >> Oracle

automatisera rollback script oracle

DBMS_METADATA_DIFF och några metadatafrågor kan automatisera denna process.

Det här exemplet visar 6 typer av ändringar:1) lägga till en kolumn 2) öka en sekvens 3) ta bort en tabell 4) skapa en tabell 5) ändra en vy 6) allokera en omfattning.

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;

Du har rätt i att DBMS_METADATA_DIFF inte fungerar för CREATE eller DROP . Att försöka skilja på ett objekt som bara finns i ett schema kommer att generera ett felmeddelande så här:

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

Men att släppa och lägga till objekt kan vara lätt att skripta med följande:

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

Ändringarna kan hanteras med en SQL-sats så här:

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

Några anteckningar om dessa resultat:

  • ADD_COLUMN fungerar som förväntat.
  • ALLOCATE_EXTENT är förmodligen en falsk positiv, jag tvivlar på att du bryr dig om uppskjutet segmentskapande. Det är mycket osannolikt att det påverkar ditt system.
  • CHANGE_VIEW fungerar inte alls. Men som med de tidigare metadatafrågorna borde det finnas ett relativt enkelt sätt att bygga det här skriptet med DBA_VIEWS.
  • INCREMENT_SEQUENCE fungerar för bra. För det mesta bryr sig en applikation inte om sekvensvärdena. Men ibland när saker inte är synkroniserade måste du ändra dem. Denna RESTART START WITH syntax kan vara till stor hjälp. Du behöver inte släppa eller återskapa indexen, eller bråka med increment by flera gånger. Denna syntax finns inte i 12c-manualen. Jag kan faktiskt inte hitta det någonstans på Google. Det verkar som att det här paketet använder odokumenterade funktioner.

Några andra anteckningar:

  • Paketet kan ibland vara väldigt långsamt.
  • Om nätverkslänkar på servern är ett problem måste du köra det genom en lokal instans med länkar till båda servrarna.
  • Det kan finnas falska positiva resultat. Ibland returnerar den en rad med bara ett mellanslag i.

Det är möjligt att helt automatisera denna process. Men baserat på frågorna ovan och min erfarenhet av alla sådana automatiserade verktyg, du bör inte lita på det till 100%.




  1. Hur tar jag reda på vilken transaktion som orsakar en väntar på tabell-metadatalås?

  2. Hur man ansluter Android till MySQL med Mysql JDBC-drivrutinen

  3. returnera värde vid en position från STRING_SPLIT i SQL Server 2016

  4. Hur kan jag förhindra SQL-injektion i PHP?