sql >> データベース >  >> RDS >> Oracle

ロールバックスクリプトオラクルの自動化

    DBMS_METADATA_DIFFといくつかのメタデータクエリにより、このプロセスを自動化できます。

    この例は、6種類の変更を示しています。1)列の追加2)シーケンスのインクリメント3)テーブルの削除4)テーブルの作成5)ビューの変更6)エクステントの割り当て

    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;
    

    正解です。DBMS_METADATA_DIFFはCREATEでは機能しません。 またはDROP 。 1つのスキーマにのみ存在するオブジェクトを差分しようとすると、次のようなエラーメッセージが生成されます。

    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
    

    ただし、オブジェクトの削除と追加は、次のように簡単にスクリプト化できる場合があります。

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

    変更は、次のようなSQLステートメントで処理できます。

    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
    

    これらの結果に関する注意事項:

    • ADD_COLUMNは期待どおりに機能します。
    • ALLOCATE_EXTENTはおそらく誤検知です。遅延セグメントの作成については、気にしないでください。システムに影響を与える可能性はほとんどありません。
    • CHANGE_VIEWはまったく機能しません。ただし、以前のメタデータクエリと同様に、DBA_VIEWSを使用してこのスクリプトを作成する比較的簡単な方法があるはずです。
    • INCREMENT_SEQUENCEはうまく機能しすぎます。ほとんどの場合、アプリケーションはシーケンス値を気にしません。しかし、物事が同期しなくなった場合、それらを変更する必要がある場合があります。このRESTART START WITH 構文は非常に役立ちます。インデックスを削除または再作成したり、increment byをいじったりする必要はありません。 複数回。この構文は12cマニュアルにはありません。実際、Googleのどこにも見つかりません。このパッケージは文書化されていない機能を使用しているようです。

    その他の注意事項:

    • パッケージが非常に遅くなる場合があります。
    • サーバー上のネットワークリンクに問題がある場合は、両方のサーバーへのリンクを持つローカルインスタンスを介して実行する必要があります。
    • 誤検知がある可能性があります。スペースだけの行が返されることもあります。

    このプロセスを完全に自動化することが可能です。しかし、上記の問題と、すべてでの私の経験に基づいています このような自動化されたツールでは、100%信頼するべきではありません。




    1. Rails:PG ::UndefinedTable:エラー:リレーション...が存在しません

    2. MariaDBでのINSERT()関数のしくみ

    3. OracleのCREATEORREPLACEVIEWに相当するSQLServer

    4. IF/ELSEステートメントを使用してSQLで新しいxmlノードエントリを更新または作成する方法