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

2つのスキーマを比較し、古いスキーマを新しいスキーマの新しい列で更新します

    スキーマ比較ツールは良い考えです。データベーススキーマは、ほとんどの人が認めるよりもはるかに複雑であり、2つのデータベーススキーマ間のすべての違いがバグを引き起こす可能性があります。

    それでも自分でやりたい場合は、スキーマ定義をテキストに抽出してから、テキスト比較を実行するのが最善の方法です。すべてがアルファベット順に並べ替えられている限り、Microsoft Word(またはFC.EXE、DIFF、または同等のもの)のドキュメントの比較機能を使用して、違いを強調することができます。

    次のSQLPlusスクリプトは、比較できるように、スキーマ定義をアルファベット順に出力します。 2つのセクションがあります。最初のセクションでは、各列を次の形式で一覧表示します。

    table_name.column_name: data_type = data_default <nullable>
    

    2番目のセクションでは、次のようにインデックスと制約をリストします。

    PK constraint_name on table_name (pk_column_list)
    FK constraint_name on table_name (fk_column_list)
    CHECK constraint_name on table_name (constraint_definition)
    

    このスクリプトは、Oracleスキーマの詳細の一部を抽出するための便利なリファレンスとして機能します。これは、クライアントサイトに出かけていて、通常のツールを利用できない場合や、セキュリティポリシーにより、自分のPCからクライアントサイトのデータベースに直接アクセスできない場合に知っておくとよい知識です。

    set serveroutput on;
    set serveroutput on size 1000000;
    declare
      rowcnt    pls_integer := 0;
      cursor c_column is
         select table_name, column_name, data_type, 
            data_precision, data_length, data_scale, 
            data_default, nullable,
            decode(data_scale, null, null, ',') scale_comma,
            decode(default_length, null, null, '= ') default_equals
          from all_tab_columns where owner = 'BCC'
          order by table_name, column_name;
      cursor c_constraint is
          select c.table_name, c.constraint_name,
             decode(c.constraint_type,
                    'P','PK',
                    'R','FK',
                    'C','CHECK',
                     c.constraint_type) constraint_type,
             c.search_condition, 
             cc.column_1||cc.comma_2||cc.column_2||cc.comma_3||cc.column_3||cc.comma_4||cc.column_4||
             cc.comma_5||cc.column_5||cc.comma_6||cc.column_6||cc.comma_7||cc.column_7 r_columns   
           from all_constraints c,
              ( select owner, table_name, constraint_name, nvl(max(position),0) max_position,
                 max( decode( position, 1, column_name, null ) ) column_1,
                 max( decode( position, 2, decode(column_name, null, null, ',' ), null ) ) comma_2,
                 max( decode( position, 2, column_name, null ) ) column_2,
                 max( decode( position, 3, decode(column_name, null, null, ',' ), null ) ) comma_3,
                 max( decode( position, 3, column_name, null ) ) column_3,
                 max( decode( position, 4, decode(column_name, null, null, ',' ), null ) ) comma_4,
                 max( decode( position, 4, column_name, null ) ) column_4,
                 max( decode( position, 5, decode(column_name, null, null, ',' ), null ) ) comma_5,
                 max( decode( position, 5, column_name, null ) ) column_5,
                 max( decode( position, 6, decode(column_name, null, null, ',' ), null ) ) comma_6,
                 max( decode( position, 6, column_name, null ) ) column_6,
                 max( decode( position, 7, decode(column_name, null, null, ',' ), null ) ) comma_7,
                 max( decode( position, 7, column_name, null ) ) column_7
               from all_cons_columns
               group by owner, table_name, constraint_name ) cc
           where c.owner = 'BCC'
           and c.generated != 'GENERATED NAME'
           and cc.owner = c.owner
           and cc.table_name = c.table_name
           and cc.constraint_name = c.constraint_name
           order by c.table_name, 
              decode(c.constraint_type,
                     'P','PK',
                     'R','FK',
                     'C','CHECK',
                     c.constraint_type) desc, 
              c.constraint_name;
    begin
      for c_columnRow in c_column loop
        dbms_output.put_line(substr(c_columnRow.table_name||'.'||c_columnRow.column_name||': '||
                             c_columnRow.data_type||'('||
                             nvl(c_columnRow.data_precision, c_columnRow.data_length)||
                             c_columnRow.scale_comma||c_columnRow.data_scale||') '||
                             c_columnRow.default_equals||c_columnRow.data_default||
                             ' <'||c_columnRow.nullable||'>',1,255));
        rowcnt := rowcnt + 1;
      end loop;
      for c_constraintRow in c_constraint loop
        dbms_output.put_line(substr(c_constraintRow.constraint_type||' '||c_constraintRow.constraint_name||' on '||
                             c_constraintRow.table_name||' ('||
                             c_constraintRow.search_condition||
                             c_constraintRow.r_columns||') ',1,255));
        if length(c_constraintRow.constraint_type||' '||c_constraintRow.constraint_name||' on '||
                             c_constraintRow.table_name||' ('||
                             c_constraintRow.search_condition||
                             c_constraintRow.r_columns||') ') > 255 then
           dbms_output.put_line('... '||substr(c_constraintRow.constraint_type||' '||c_constraintRow.constraint_name||' on '||
                                c_constraintRow.table_name||' ('||
                                c_constraintRow.search_condition||
                                c_constraintRow.r_columns||') ',256,251));
        end if;
        rowcnt := rowcnt + 1;
      end loop;
    end;
    /
    

    残念ながら、いくつかの制限があります:

    1. data_defaultsに埋め込まれたキャリッジリターンと空白、およびチェック制約の定義は、スキーマへの影響がない場合でも、差異として強調表示される場合があります。
    2. 代替キー、一意のインデックス、またはパフォーマンスインデックスは含まれません。これには、all_ind_columnsおよびall_indexesカタログビューを参照する、スクリプト内の3番目のSELECTステートメントが必要になります。
    3. セキュリティの詳細、同義語、パッケージ、トリガーなどは含まれません。パッケージとトリガーは、最初に提案したものと同様のアプローチを使用して比較するのが最適です。スキーマ定義の他の側面を上記のスクリプトに追加できます。
    4. 上記のFK定義は、参照している外部キー列を識別しますが、参照されているPKまたはテーブルは識別しません。もう1つ、私がやったことのない詳細を説明します。

    スクリプトを使用しなくても。このようなもので遊ぶことには、技術者にとって一定の喜びがあります。;-)

    マシュー



    1. 計算実行時のスケールの損失

    2. 死のphp白い画面

    3. 接続がタイムアウトしました:Nodejs GoogleAppEngineからCloudMySqlへ

    4. Rails:MySQLからPostGresに変換すると、Geokitの距離計算が壊れますか?