27 エディションベースの再定義の使用

エディションベースの再定義(EBR)を使用すると、アプリケーションの使用中にそのデータベース・コンポーネントをアップグレードでき、停止時間を最小化あるいは排除することができます。

トピック:

エディションベースの再定義の概要

アプリケーションを使用中にアップグレードするには、アプリケーションのデータベース・コンポーネントを構成するデータベース・オブジェクトをコピーし、コピーしたオブジェクトを個別に再定義する必要があります。アプリケーションのユーザーは、この変更による影響を受けず、変更されていないアプリケーションを引き続き実行できます。変更が正しいことを確認できたら、アップグレードしたアプリケーションをすべてのユーザーが使用できるようにします。

EBRでは、1つ以上のコンポーネント機能を使用します。使用する機能と停止時間は次の要素によって異なります。

  • 再定義するデータベース・オブジェクトの種類

  • データベース・オブジェクトの再定義中に、ユーザーがそのデータベース・オブジェクトをどの程度使用できるか

  • 以前のアプリケーションを使用しているユーザーがいるときに、アップグレードしたアプリケーションを他のユーザーが使用できるようにするかどうか

データベース・オブジェクトをコピーし、コピーしたデータベース・オブジェクトを分離した状態で再定義するには、常にエディション機能を使用します。この章で説明するオンラインでのアプリケーション・アップグレード手順がエディションベースの再定義(EBR)と呼ばれるのはこのためです。

再定義するすべてのオブジェクトがエディション化(定義は「エディション・オブジェクトと非エディション・オブジェクト」を参照)されている場合、使用する機能はエディションのみです。

表はエディション・オブジェクトではありません。1つ以上の表の構造を変更する場合は、エディショニング・ビュー機能も使用します。

表の構造を変更している間、他のユーザーがその表のデータを変更する必要がある場合は、forward crosseditionトリガーも使用します。アップグレード前のアプリケーションとアップグレード後のアプリケーションが同時に通常使用(ホット・ロールオーバー)されている場合、reverse crosseditionトリガーも使用します。crosseditionトリガーはアプリケーションの永続的な要素ではありません。全ユーザーがアップグレード後のアプリケーションを使用するようになったら削除します。

あるアプリケーションが他のエディションでも実行される場合に、1つのエディションでそのアプリケーションに対して実行可能なEBR操作は、ライブ操作です。

エディション

エディションは非スキーマ・オブジェクトであり、所有者が存在しません。エディションは1つのネームスペースに作成されます。複数のエディションがデータベースに共存することができます。

データベースには少なくとも1つのエディションが必要です。新規作成またはアップグレードされたOracle Databaseはすべて、ora$baseという名前の1つのエディションから開始されます。

トピック:

エディション・オブジェクトと非エディション・オブジェクト

注意:

ユーザースキーマという用語は同義です。スキーマ・オブジェクトの所有者は、これを所有するユーザー/スキーマです。

エディション・オブジェクトには、所有者でエディション対応のスキーマ・オブジェクト・タイプとEDITIONABLEプロパティの両方があります。エディションにはエディション・オブジェクトの独自のコピーがあり、そのエディションに対してはこのコピーのみが表示可能です。

非エディション・オブジェクトには、所有者で非エディション対応のスキーマ・オブジェクト・タイプまたはNONEDITIONABLEプロパティのいずれかがあります。エディションは、非エディション・オブジェクトの独自のコピーを持つことはできません。非エディション・オブジェクトは、すべてのエディションに対して表示可能です。

オブジェクトは、その所有者におけるそのタイプに対するエディションの有効化によってエディション・オブジェクトになる場合、潜在的にエディション対応になります。

エディション・オブジェクトは、スキーマとエディションの両方に属し、そのOBJECT_NAMEOWNER、およびEDITION_NAMEにより一意に識別されます。非エディション・オブジェクトは、スキーマのみに属し、そのOBJECT_NAMEおよびOWNERにより(EDITION_NAMENULL)一意に識別されます。(厳密に言えば、オブジェクトを一意に識別するにはオブジェクトのNAMESPACEも必要ですが、オブジェクトを参照する文では暗黙的または明示的にNAMESPACEが指定されるので、これは無視しても構いません)。

オブジェクトのOBJECT_NAMEOWNER、およびEDITION_NAMEは、静的データ・ディクショナリ・ビュー*_OBJECTSおよび*_OBJECTS_AEに表示できます。

オブジェクトのEDITION_NAMEを知らなくても、このオブジェクトを参照できます(知っていても、指定できません)。参照のコンテキストで、エディションを暗黙的に指定します。コンテキストがデータ定義言語(DDL)文である場合、エディションは、このコマンドを発行したセッションの現行エディションです。コンテキストがソース・コードである場合、エディションは、オブジェクトが実オブジェクトであるものです。

トピック:

エディション・オブジェクトと非エディション・オブジェクトの名前解決

オブジェクト名の解決を試行するために、Oracle Databaseは、「スキーマの範囲内での名前解決」で説明されている手順を使用します。プロシージャを正常に実行するには、オブジェクト名のすべての部分が現行エディションで表示されている必要があります。

エディション・オブジェクトの名前解決時には、現行エディションのエディション・オブジェクトと非エディション・オブジェクトの両方が表示可能です。

非エディション・オブジェクトの名前解決時には、非エディション・オブジェクトのみが表示可能です。したがって、エディション・オブジェクトを参照する非エディション・オブジェクトを作成しようとすると(「エディション・オブジェクトに依存可能な非エディション・オブジェクト」で説明されている場合を除く)、作成は失敗し、エラーが表示されます。

参照対象のエディション・オブジェクトを変更する場合、そのすべての依存(直接および間接)が無効になります。無効なオブジェクトが参照されると、データベースはそのオブジェクトを検証しようとします。

関連項目:

エディション・オブジェクトに依存可能な非エディション・オブジェクト

通常、非エディション・オブジェクトはエディション・オブジェクトに依存できません。これは、名前解決時にはエディション・オブジェクトは表示できないためです。ただし、非エディション・オブジェクトは、名前解決時にエディション・オブジェクトを検索するためにエディション(評価エディション)を指定すると、エディション・オブジェクトに依存できます。評価エディションを指定するには、非エディション・オブジェクトは次のいずれかである必要があります。

  • マテリアライズド・ビュー

  • 仮想列

トピック:

マテリアライズド・ビュー

マテリアライズド・ビューは、評価エディションを指定することによってエディション・オブジェクトに依存できるようにする非エディション・オブジェクトです。エディション・オブジェクトに依存するマテリアライズド・ビューは、query_rewrite_clauseで指定する特定のエディション範囲内の問合せリライトに対してのみ適格な場合があります。

マテリアライズド・ビューを作成するための簡単な構文は、次のとおりです。

CREATE MATERIALIZED VIEW [ schema.] materialized_view other_clauses
[ evaluation_edition_clause ] [ query_rewrite_clause ] AS subquery

この場合、evaluation_edition_clauseは、次のとおりです。

EVALUATE USING { CURRENT EDITION | EDITION edition | NULL EDITION }

また、query_rewrite_clauseは、次のとおりです。

{ DISABLE | ENABLE } QUERY REWRITE
[ unusable_before_clause ] [ unusable_beginning_clause ]

この場合、unusable_before_clauseは、次のとおりです。

UNUSABLE BEFORE { CURRENT EDITION | EDITION edition }

また、unusable_beginning_clauseは、次のとおりです。

UNUSABLE BEGINNING WITH { CURRENT EDITION | EDITION edition | NULL EDITION }

CURRENT EDITIONは、DDL文が実行されるエディションを指します。NULL EDITIONを指定することは、これが含まれる句を省略することと同じです。evaluation_edition_clauseを省略すると、名前解決時にエディション・オブジェクトは表示できなくなります。

評価エディションまたは使用不可エディションを無効化、有効化または変更するには、ALTER MATERIALIZED VIEW文を使用します。

マテリアライズド・ビューの評価エディションおよび使用不可エディションを表示するには、静的データ・ディクショナリ・ビュー*_MVIEWSを使用します。

評価エディションを削除すると、マテリアライズド・ビューが無効になります。マテリアライズド・ビューが使用可能なエディションを削除しても、マテリアライズド・ビューは無効になりません。

関連項目:

CREATE MATERIALIZED VIEW文の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

『Oracle Database SQL言語リファレンス』

Oracle Databaseリファレンス

仮想列

仮想列(生成列とも呼ばれます)は、ディスク領域を使用しません。データベースは、式を評価することによってリクエストごとに仮想列で値を生成します。式によってPL/SQLファンクションを起動できます(PL/SQLファンクションはエディション・オブジェクトでもかまいません)。仮想列は、評価エディションを指定することにより、エディション化PL/SQLファンクションを起動する式に依存できるようにします。

仮想列を作成するための構文は、次のとおりです。

column [ datatype ] [ GENERATED ALWAYS ] AS ( column_expression )
[ VIRTUAL ] [ evaluation_edition_clause ]
[ unusable_before_clause ] [ unusable_beginning_clause ]
[ inline_constraint ]...

evaluation_edition_clauseの詳細は、「マテリアライズド・ビュー」を参照してください。

仮想列が起動するファンクションの依存性は保持されません。したがって、評価エディションが削除されるか、仮想列が非エディション・ファンクションに依存しているときに、ファンクションがエディション化されると、次のいずれかの例外が発生する可能性があります。

  • 仮想列の問合せ試行

  • 仮想列が含まれる行の更新試行

  • 仮想列へのアクセスを試行するトリガー

仮想列の評価エディションを表示するには、静的データ・ディクショナリ・ビュー*_TAB_COLSを使用します。

関連項目:

エディション対応、およびエディション非対応スキーマ・オブジェクト・タイプ

スキーマ内のスキーマ・オブジェクト・タイプをエディション対応にするには、データベース内でエディション対応にする必要があります。データベース内でエディション対応であるスキーマ・オブジェクト・タイプは、COMPATIBLE初期化パラメータの値によって決定され、動的パフォーマンス・ビューV$EDITIONABLE_TYPESによって表示されます。

COMPATIBLEの値が12以上である場合、データベース内で次のスキーマ・オブジェクト・タイプがエディション対応になります。

  • SYNONYM

  • VIEW

  • SQL翻訳プロファイル

  • すべてのPL/SQLオブジェクト型:

    • FUNCTION

    • LIBRARY

    • PACKAGEおよびPACKAGE BODY

    • PROCEDURE

    • TRIGGER

    • TYPEおよびTYPE BODY

他のすべてのスキーマ・オブジェクト・タイプはデータベースおよびすべてのスキーマ内で非エディション対応であり、そのタイプのオブジェクトは常にエディション化されません。非エディション対応スキーマ・オブジェクト・タイプの例はTABLEです。表は常に非エディション化オブジェクトです。

スキーマ・オブジェクト・タイプがデータベース内でエディション対応である場合、スキーマ内でエディション対応にできます。

関連項目:

ユーザーに対するエディションの有効化

注意:

  • エディションの有効化は、ライブ操作ではありません。

  • データベースがリリース11.2からリリース12.1にアップグレードされると、アップグレード前のデータベースでエディションに対して有効であったユーザーは、アップグレード後のデータベースでもエディションに対して有効になり、デフォルトのスキーマ・オブジェクト・タイプはこれらのスキーマでエディション対応になります。デフォルトのスキーマ・オブジェクト・タイプは、静的データ・ディクショナリ・ビューDBA_EDITIONED_TYPESによって表示されます。アップグレード前のデータベースでエディションに対して無効だったユーザーは、アップグレード後のデータベースでもエディションに対して無効であり、スキーマ・オブジェクト・タイプはこれらのスキーマではエディション対応になりません。

  • エディションが有効になっているユーザー確認するには、静的データ・ディクショナリ・ビューDBA_USERSまたはUSER_USERSEDITIONS_ENABLED列を参照してください。

ユーザーに対してエディションを有効化するには、CREATE USER、またはALTER USER文のENABLE EDITIONS句を使用します。

ALTER USER文を使用すると、スキーマ内でエディション対応になるスキーマ・オブジェクト・タイプを指定できます。

ALTER USER user ENABLE EDITIONS [ FOR type [, type ]... ]

FORリストから省略するタイプはすべて、データベース内でエディション対応であるとしても、スキーマ内で非エディション対応になります。(タイプがデータベース内で非エディション対応である場合、このタイプはすべてのスキーマ内で常に非エディション対応になります。)

ALTER USER文からFORリストを省略するか、CREATE USER文を使用してユーザーに対してエディションを有効化すると、スキーマ内でエディション対応になるタイプは、静的データ・ディクショナリ・ビューDBA_EDITIONED_TYPES (『Oracle Databaseリファレンス』を参照)によってこのスキーマに対して表示されるタイプです。

エディションの有効化は遡及的で、これを元に戻すことはできません。ユーザーに対してエディションを有効化すると、このユーザーは永続的にエディション対応になります。スキーマ内のスキーマ・オブジェクト・タイプに対してエディションを有効化すると、このタイプはそのスキーマ内で永続的にエディション対応になります。エディション対応のユーザーが所有するか所有予定のオブジェクトはすべて、そのタイプがスキーマ内でエディション対応であるとともにEDITIONABLEプロパティを持つ場合、エディション・オブジェクトになります。EDITIONABLEプロパティの詳細は、「EDITIONABLEおよびNONEDITIONABLEプロパティ」を参照してください。

トピック:

関連項目:

CREATE USERおよびALTER USERの各文の完全な構文とセマンティクスの詳細は、『Oracle Database SQL言語リファレンス』を参照してください

DBA_EDITIONED_TYPESの詳細は、『Oracle Databaseリファレンス』を参照してください。

DBA_USERSの詳細は、『Oracle Databaseリファレンス』を参照してください。

USER_USERSの詳細は、『Oracle Databaseリファレンス』を参照してください。

エディション化されていない依存を持つ潜在的なエディション・オブジェクト

潜在的なエディション・オブジェクトにエディション化されていない依存がある場合、潜在的なエディション・オブジェクトの所有者に対してエディションを有効化できるのは、次のいずれかが該当する場合のみです。

  • 潜在的なエディション・オブジェクトの所有者に対してエディションを有効化すると、エディション化されていない依存がエディション化される場合。

  • 次のように、FORCEを指定します。

    ALTER USER user ENABLE EDITIONS [ FOR type [, type ]... ] FORCE;
    

    前述の文では、指定されたユーザーについてエディションは有効化され、エディション・オブジェクトに対する非エディション依存オブジェクトは無効化されます。

注意:

前述の文が、抽象データ型(ADT)を含む非エディション依存オブジェクトを無効化し、ユーザーが、無効化されたオブジェクトが依存するエディション・オブジェクトを含むエディションを削除した場合、無効化されたオブジェクトを再コンパイルすることはできません。したがって、オブジェクトは無効のままになります。

FORCEは、次の状況で便利です。ユーザーABに対してエディションを有効化する必要がある場合。ユーザーAが潜在的エディション・オブジェクトa1a2の所有者である場合。ユーザーBが潜在的エディション・オブジェクトb1b2の所有者である場合。オブジェクトa1がオブジェクトb1に依存している場合。オブジェクトb2がオブジェクトa2に依存している場合。ユーザーABに対してエディションを有効化させるには、次のようにします。

  1. FORCEを使用して、ユーザーAについてエディションを有効化します。

    ALTER USER A ENABLE EDITIONS FORCE;
    

    これで、a1a2はエディション・オブジェクトになり、非エディション・オブジェクトb2 (a2に依存するもの)は無効になりました。

  2. ユーザーBのエディションを有効化します。

    ALTER USER B ENABLE EDITIONS;
    

    これで、b1b2はエディション・オブジェクトになります。ただし、b2は無効のままです。

  3. COMPILEで、適切なALTER文を使用して、b2を再コンパイルします。PL/SQLオブジェクトについては、REUSE SETTINGSも指定してください。

    たとえば、b2がプロシージャの場合、次の文を使用します。

    ALTER PROCEDURE b2 COMPILE REUSE SETTINGS
    

FORCEは、次の状況では必要ありません。潜在的エディション・オブジェクトc1を所有しているユーザーCに対してエディションを有効化する必要がある場合。オブジェクトc1が、ユーザーDにより所有されていて、潜在的エディション依存オブジェクトd1を持っている場合。ユーザーDが、所有者がCである依存オブジェクトを持つ、潜在的エディション・オブジェクトを所有していない場合。最初にd1をエディション・オブジェクトにして、Dに対してエディションを有効化した場合、非エディション・オブジェクトはエディション・オブジェクトに依存できないという規則に違反せずに、Cに対してエディションを有効化することができます。

関連項目:

エディションを有効化できないユーザー

次のユーザーに対してはエディションを有効化できません。

  • Oracleが保持しているユーザー

    Oracleが保持しているユーザーでは、*_USERSビューの列ORACLE_MAINTAINEDの値はYです。

  • CDBの共通ユーザー

  • 1つ以上の進化したADTを所有するユーザー。

    有効化しようとすると、エラーORA-38820が発生します。ADTが表への依存性を持っていない場合、ALTER TYPE RESET文を使用して、バージョンを1にリセットすることにより、それ以上、表が進化するとみなされないようにすることができます(ADTのバージョンを1にリセットすると、これに依存するものは無効化されます。)

関連項目:

EDITIONABLEおよびNONEDITIONABLEプロパティ

注意:

データベースをリリース11.2からリリース12.1にアップグレードすると、ユーザーが作成したスキーマ内のオブジェクトがEDITIONABLEプロパティを取得し、パブリック・シノニムがNONEDITIONABLEプロパティを取得します。

データベース内でエディション対応であるスキーマ・オブジェクト・タイプに対してCREATEおよびALTER文を使用すると、作成または変更するオブジェクトをEDITIONABLEまたはNONEDITIONABLEとして指定できます。

DBMS_SQL_TRANSLATOR.CREATE_PROFILEプロシージャを使用すると、作成するSQL翻訳プロファイルをEDITIONABLEまたはNONEDITIONABLEとして指定できます。

どのオブジェクトがEDITIONABLEかを確認するには、静的データ・ディクショナリ・ビュー*_OBJECTSまたは*_OBJECTS_AEEDITIONABLE列を参照してください。

トピック:

関連項目:

  • PL/SQLスキーマ・オブジェクトのCREATEおよびALTER文の構文とセマンティクスの詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください

  • SQLスキーマ・オブジェクトのCREATEおよびALTER文の構文とセマンティクスの詳細は、『Oracle Database SQL言語リファレンス』を参照してください

  • DBMS_SQL_TRANSLATOR.CREATE_PROFILEプロシージャの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください

  • *_OBJECTSの詳細は、『Oracle Databaseリファレンス』を参照してください。

  • *_OBJECTS_AEの詳細は、『Oracle Databaseリファレンス』を参照してください。

新規EDITIONABLEおよびNONEDITIONABLEオブジェクトの作成

データベース内でタイプがエディション対応である新規スキーマ・オブジェクトを作成する場合、EDITIONABLEまたはNONEDITIONABLEプロパティを指定できます。このプロパティを省略する場合、オブジェクトは次のいずれかでないかぎり、デフォルトではEDITIONABLEになります。

  • PUBLIC SYNONYM (デフォルトではNONEDITIONABLEです)

  • PACKAGE BODY (パッケージ仕様のプロパティを継承します)

  • TYPE BODY (タイプ仕様のプロパティを継承します)

PACKAGE BODYまたはTYPE BODYでは、プロパティを指定する場合、対応するパッケージまたはタイプ仕様のプロパティと一致する必要があります。

それ自体のスキーマ内でエディション対応であるタイプのEDITIONABLEオブジェクトを作成する場合、新規オブジェクトは、オブジェクトの作成時に現行エディションであるエディションでのみ表示可能なエディション・オブジェクトです。エディション・オブジェクトの作成は、新規オブジェクトを表示できないエディションに関してのライブ操作です。

NONEDITIONABLEプロパティを持つオブジェクト、またはそれ自体のスキーマ内で非エディション対応であるタイプのオブジェクトを作成する場合、新規オブジェクトは、すべてのエディションで表示可能な非エディション・オブジェクトです。

現行エディションでは、objという名前のスキーマ・オブジェクトがスキーマ内にあるが、別のエディションでは、objという名前のエディション・オブジェクトがスキーマ内にあるとします。現行エディションのスキーマでは、objという名前のオブジェクトを作成できますが、これはエディション・オブジェクトである(つまり、OBJECT_NAMEOWNERおよびEDITION_NAMEにより一意に識別される)必要があります。新規オブジェクトのタイプ(同じ名前を持つ既存のエディション・オブジェクトのタイプとは異なる場合があります)はスキーマ内でエディション対応である必要があり、新規オブジェクトはEDITIONABLEプロパティを持つ必要があります。

EDITIONABLEおよびNONEDITIONABLEオブジェクトの置換および変更

既存のオブジェクトを(CREATE OR REPLACEまたはALTER文を使用して)置換または変更する場合、次のようになります。

  • スキーマがエディションに対して有効化されていない場合、オブジェクトのプロパティをEDITIONABLEからNONEDITIONABLE (またはこの逆)に変更できます。

  • 置換または変更対象のオブジェクトのタイプについてスキーマがエディションに対して有効化されている場合、オブジェクトのプロパティをEDITIONABLEからNONEDITIONABLE (またはこの逆)に変更できません。

エディション・オブジェクトの変更は、変更されたオブジェクトを表示できないエディションに関してのライブ操作です。

エディション・オブジェクトの規則
  • 非エディション・オブジェクトは、通常は、エディション・オブジェクトに依存できません。

  • 抽象データ型(ADT)をエディション化し、同時に進化させることはできません。

  • エディション・オブジェクトを、FOREIGN KEY制約の始点、または終点にすることはできません。

    この規則は、エディション・ビューに対してのみ影響します。エディション化されたビューとは、通常のビュー、またはエディショニング・ビューのどちらかです。

エディションの作成

エディションを作成するには、SQL文CREATE EDITIONを使用します。

エディションは既存のエディションの子として作成する必要があります。CREATE EDITION文によって作成される最初のエディションの親はora$baseです。次の文によって、ora$baseの子としてエディションe2が作成されます。

CREATE EDITION e2

(「例: エディション・オブジェクトおよび変更時のコピー」およびその他は前述の文を使用します。)

エディションの子は最大で1つです。

エディションの子孫は、エディションの子、子の子、その子などを指します。エディションの祖先は、エディションの親、親の親、その親などを指します。ルート・エディションには親はありません。また、リーフ・エディションには子はありません。

関連項目:

エディション・オブジェクトおよび変更時のコピー

エディションを作成すると、親エディションのエディション・オブジェクトがすべてこのエディションにコピーされます。1つのエディション内のエディション・オブジェクトを変更しても、他のエディション内のこのエディション・オブジェクトのコピーには影響しません。

前述のパラグラフでは、どのような処理が行われるかを概念的に説明しています。実際には、パフォーマンスを最適化するために、Oracle Databaseがエディション・オブジェクトを祖先エディションから子孫エディションにコピーするのは、子孫エディションがオブジェクトを変更する場合のみです。この方法は変更時のコピーと呼ばれます。

子孫エディションに(実際にではなく)概念的にコピーされたエディション・オブジェクトは、継承オブジェクトと呼ばれます。子孫エディションのユーザーがDDL文で継承オブジェクトを参照すると、Oracle Databaseはオブジェクトを子孫エディションに実際にコピーします。このコピー操作は実現化と呼ばれ、子孫エディションで実オブジェクトが作成されます。

注意:

前述のパラグラフの実現化規則には例外が1つあります。CREATE OR REPLACE object文によって継承オブジェクトが同一オブジェクト(つまり、ソース・コードおよび設定が同じオブジェクト)に置換された場合、Oracle Databaseは子孫エディションで実オブジェクトを作成しません

例: エディション・オブジェクトおよび変更時のコピー

例27-1では、エディションora$baseでプロシージャhelloを作成してから、ora$baseの子としてエディションe2を作成します。e2helloを起動するときは、ora$baseで継承プロシージャを起動します。このとき、e2helloを変更して、実オブジェクト化します。ここで、e2helloを起動するときは、独自の実プロシージャを起動します。エディションora$base内のプロシージャhelloは変更されずに残ります。

例27-1 エディション・オブジェクトおよび変更時のコピー

  1. 次のプロシージャがora$baseでエディション・オブジェクトであると仮定します。

    CREATE OR REPLACE PROCEDURE hello IS
      BEGIN
        DBMS_OUTPUT.PUT_LINE('Hello, edition 1.');
      END hello;
    /
    
  2. ora$baseで、プロシージャを起動します。

    BEGIN hello(); END;
    /
    

    結果:

    Hello, edition 1.
     
    PL/SQL procedure successfully completed.
    
  3. 子エディションを作成します。

    CREATE EDITION e2;
    

    概念的に、プロシージャが子エディションにコピーされ、子エディションではこのコピーのみが表示可能です。このコピーは継承オブジェクトであり、実オブジェクトではありません。

  4. 子エディションを使用します。

    ALTER SESSION SET EDITION = e2;
    

  5. プロシージャを起動します。

    BEGIN hello(); END;
    /
    

    概念的に、子エディションはプロシージャ(これは親エディションora$base内のプロシージャと同等です)の独自のコピーを起動します。ただし、子エディションは実際には親エディション内のプロシージャを起動します。結果:

    Hello, edition 1.
     
    PL/SQL procedure successfully completed.
    
  6. プロシージャを変更します。

    CREATE OR REPLACE PROCEDURE hello IS
      BEGIN
        DBMS_OUTPUT.PUT_LINE('Hello, edition 2.');
      END hello;
    /
    

    Oracle Databaseは子エディション内のプロシージャを実現化し、変更は、親エディション内のプロシージャではなく、子エディション内の実オブジェクトにのみ影響します。

  7. プロシージャを起動します。

    BEGIN hello(); END;
    /
    

    子エディションは独自の実プロシージャを起動します。

    Hello, edition 2.
    
    PL/SQL procedure successfully completed.
    
  8. 親エディションに戻ります。

    ALTER SESSION SET EDITION = ora$base;
    
  9. プロシージャを起動し、これが変更されていないことを確認します。

    BEGIN hello(); END;
    /
    

    結果:

    Hello, edition 1.
     
    PL/SQL procedure successfully completed.
    

関連項目:

ALTER SESSION SET EDITIONの詳細は、「セッション・エディションの変更」を参照してください。

例: エディション・オブジェクトの削除

例27-2は、エディションora$baseでプロシージャgoodbyeを作成してから、ora$baseの子としてエディションe2を作成します。e2goodbyeが削除されると、e2はgoodbyeを起動できなくなりますが、ora$baseでは起動できます

e2でプロシージャgoodbyeが削除されたため、次のようになります。

  • 子孫では、プロシージャgoodbyeが継承されません。

  • goodbyeというオブジェクトはe2で表示可能でないため、e2では、goodbyeという名前を付けてオブジェクトを作成できますが、これはエディション・オブジェクトである必要があります。goodbyeという名前の新規エディション・オブジェクトをe2が作成すると、e2の子孫がこのオブジェクトを継承します。

例27-2 エディション・オブジェクトの削除

  1. 次のプロシージャがora$baseでエディション・オブジェクトであると仮定します。

    CREATE OR REPLACE PROCEDURE goodbye IS
      BEGIN
        DBMS_OUTPUT.PUT_LINE('Good-bye!');
      END goodbye;
    /
    
  2. プロシージャを起動します。

    BEGIN goodbye; END;
    /
    

    結果:

    Good-bye!
     
    PL/SQL procedure successfully completed.
    
  3. ora$baseの子としてエディションe2を作成します。

    CREATE EDITION e2;
    

    e2では、プロシージャは継承オブジェクトです。

  4. エディションe2を使用します。

    ALTER SESSION SET EDITION = e2;
    

    ALTER SESSION SET EDITIONはトップレベルのSQL文である必要があります。

  5. e2で、プロシージャを起動します。

    BEGIN goodbye; END;
    /
    

    e2ora$baseでプロシージャを起動します。

    Good-bye!
     
    PL/SQL procedure successfully completed.
    
  6. e2で、プロシージャを削除します。

    DROP PROCEDURE goodbye;
    
  7. e2で、削除したプロシージャの起動を試行します。

    BEGIN goodbye; END;
    /
    

    結果:

    BEGIN goodbye; END;
          *
    ERROR at line 1:
    ORA-06550: line 1, column 7:
    PLS-00201: identifier 'GOODBYE' must be declared
    ORA-06550: line 1, column 7:
    PL/SQL: Statement ignored
    
  8. ora$baseに戻ります。

    ALTER SESSION SET EDITION = ora$base;
    
  9. ora$baseで、プロシージャを起動します。

    BEGIN goodbye; END;
    /
    

    結果:

    Good-bye!
     
    PL/SQL procedure successfully completed.
    

関連項目:

例: 削除済継承オブジェクトの名前を使用したオブジェクトの作成

例27-3では、e2goodbyeという名前のファンクションが作成され、その後、e2の子としてe3という名前のエディションが作成されます。e3プロシージャgoodbye(e2で削除)を起動しようとすると、エラーが発生しますが、e3ファンクションgoodbye(e2で作成)は正常に起動されます。

例27-3 削除済継承オブジェクトの名前を使用したオブジェクトの作成

  1. e2に戻ります。

    ALTER SESSION SET EDITION = e2;
    
  2. e2で、goodbyeという名前のファンクションを作成します。

    CREATE OR REPLACE FUNCTION goodbye
      RETURN BOOLEAN
    IS
    BEGIN
      RETURN(TRUE);
    END goodbye;
    /
    

    このファンクションはエディション・オブジェクトである必要があります。デフォルトでは、これはEDITIONABLEプロパティを持ちます。タイプFUNCTIONがスキーマ内でエディション対応ではない場合、ALTER USER文を使用してエディション対応にする必要があります。

  3. エディションe3を作成します。

    CREATE EDITION e3 AS CHILD OF e2;
    

    エディションe3がファンクションgoodbyeを継承します。

  4. エディションe3を使用します。

    ALTER SESSION SET EDITION = e3;
    
  5. e3で、プロシージャgoodbyeの起動を試行します。

    BEGIN
      goodbye;
    END;
    /
    

    結果:

    ERROR at line 2:
    ORA-06550: line 2, column 3:
    PLS-00306: wrong number or types of arguments in call to 'GOODBYE'
    ORA-06550: line 2, column 3:
    PL/SQL: Statement ignored
    
  6. e3で、ファンクションgoodbyeを起動します。

    BEGIN
      IF goodbye THEN
        DBMS_OUTPUT.PUT_LINE('Good-bye!');
      END IF;
    END;
    /
    

    結果:

    Good-bye!
     
    PL/SQL procedure successfully completed.

関連項目:

一部のユーザーに対してエディションを使用可能にする

エディションの作成者には、エディションに対するUSE権限WITH GRANT OPTIONが自動的に付与されます。他のユーザーにエディションのUSE権限を付与するには、SQL文GRANT USE ON EDITIONを使用します。

関連項目:

GRANT文の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

すべてのユーザーに対してエディションを使用可能にする

すべてのユーザーがエディションを使用できるようにするには、次のいずれかの手順を実行します。

  • エディションのUSE権限をPUBLICに付与します。

    GRANT USE ON EDITION edition_name TO PUBLIC
    

  • このエディションを、データベースのデフォルト・エディションにします。

    ALTER DATABASE DEFAULT EDITION = edition_name
    

    これには、edition_nameUSE権限がPUBLICに効率的に付与されるため、すべてのユーザーがエディションを使用できるという副作用があります。

関連項目:

現行エディションとセッション・エディション

各データベース・セッションで一度に使用されるエディションは1つのみです。データベース・セッションがある時点で使用するエディションは、現行エディションと呼ばれます。データベース・セッションが開始すると、現行エディションがセッション・エディションになります。これは、データベース・セッションが開始するときのエディションです。セッション・エディションを変更すると、現行エディションも同様に変更されます。ただし、現行エディションとセッション・エディションが異なる状況もあります。

トピック:

最初のセッション・エディション

データベースに接続するときに、最初のセッション・エディションを指定できます。最初のセッション・エディションはデータベースのデフォルト・エディションか、USE権限を持っている任意のエディションにすることができます。使用できるエディションの名前を表示するには、次の問合せを使用します。

SELECT EDITION_NAME FROM ALL_EDITIONS;

接続時に最初のセッション・エディションをどのように指定するかは、データベースの接続方法によって異なります。インタフェースのドキュメントを参照してください。

関連項目:

Oracle Database 11gリリース2 (11.2.0.2)では、接続時にセッション・エディションを指定しない場合、次のようになります。

  • データベース・サービスを使用してデータベースに接続し、そのサービスで最初のセッション・エディションが指定された場合、そのサービスの最初のセッション・エディションが最初のセッション・エディションになります。

  • そうでない場合、データベースのデフォルト・エディションが最初のセッション・エディションになります。

リリース11.2.0.2では、データベース・サービスの作成または変更時に、その最初のセッション・エディションを指定できます。

データベース・サービスを作成または変更にするには、srvctl add serviceまたはsrvctl modify serviceコマンドを使用することをお薦めします。サービスのデフォルトの最初のセッション・エディションを指定するには、-editionオプションを使用します。

また、DBMS_SERVICE.CREATE_SERVICEまたはDBMS_SERVICE.MODIFY_SERVICEプロシージャを使用してデータベース・サービスを作成または変更して、EDITION属性を使用してデフォルトの最初のセッション・エディションを指定できます。

注意:

Oracle Database 11gリリース2(11.2.0.1)では、DBMS_SERVICE.CREATE_SERVICEおよびDBMS_SERVICE.MODIFY_SERVICEプロシージャは、Oracle ClusterwareおよびOracle Restartにより管理されるデータベースで非推奨です。

関連項目:

セッション・エディションの変更

データベースに接続した後で、SQL文ALTER SESSION SET EDITIONを使用してセッション・エディションを変更することができます。セッション・エディションは、データベースのデフォルト・エディションか、USE権限のある任意のエディションに変更できます。セッション・エディションを変更すると、現行エディションも同じエディションに変更されます。

「例: エディション・オブジェクトおよび変更時のコピー」および「例: エディション・オブジェクトの削除」からの次に示す文は、セッション・エディション(および現在のエディション)を最初にe2に変更し、後でora$baseに変更します。

ALTER SESSION SET EDITION = e2
...
ALTER SESSION SET EDITION = ora$base

注意:

ALTER SESSION SET EDITIONはトップレベルのSQL文である必要があります。たとえば、ログオン・トリガーでエディションの変更を遅らせるには、DBMS_SESSION.SET_EDITION_DEFERREDプロシージャを使用します。

関連項目:

現行エディション名とセッション・エディション名の表示

次の文によって、現行エディションの名前が返されます。

SELECT SYS_CONTEXT('USERENV', 'CURRENT_EDITION_NAME') FROM DUAL;

次の文によって、セッション・エディションの名前が返されます。

SELECT SYS_CONTEXT('USERENV', 'SESSION_EDITION_NAME') FROM DUAL;

関連項目:

SYS_CONTEXTファンクションの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

現行エディションがセッション・エディションと異なる状況

次のような場合に、現行エディションがセッション・エディションと異なることがあります。

  • crosseditionトリガーが起動される場合。

  • 例27-4のように、DBMS_SQL.PARSEプロシージャをコールして、文を実行するエディションを指定することで、文を実行する場合。

    文が実行している間、指定されたエディションが現行エディションになりますが、セッション・エディションは変更されません。

例27-4では、セッション・エディションと現行エディションの名前を返すファンクションが作成されます。その後、子エディションが作成され、子エディションによってそのファンクションが2回起動されます。1回目はセッション・エディションと現行エディションは同じです。2回目は異なります。別のエディションがパラメータとしてDBMS_SQL.PARSEプロシージャに渡されるためです。

例27-4 セッション・エディションと異なる現行エディション

  1. セッション・エディションと現行エディションの名前を返すファンクションを作成します。

    CREATE OR REPLACE FUNCTION session_and_current_editions
      RETURN VARCHAR2
    IS
    BEGIN
      RETURN
      'Session: '|| SYS_CONTEXT('USERENV', 'SESSION_EDITION_NAME') ||
      ' / ' ||
      'Current: '|| SYS_CONTEXT('USERENV', 'CURRENT_EDITION_NAME');
    END session_and_current_editions;
    /
    
  2. 子エディションを作成します。

    CREATE EDITION e2 AS CHILD OF ora$base;
    
  3. 子エディションを使用します。

    ALTER SESSION SET EDITION = e2;
    
  4. 関数を呼び出します。

    BEGIN
      DBMS_OUTPUT.PUT_LINE (session_and_current_editions());
    END;
    /
    

    結果:

    Session: E2 / Current: E2
     
    PL/SQL procedure successfully completed.
    
  5. 関数をもう一度呼び出します。

    DECLARE
      c     NUMBER := DBMS_SQL.OPEN_CURSOR();
      v     VARCHAR2(200);
      dummy NUMBER;
      stmt  CONSTANT VARCHAR2(32767)
        := 'SELECT session_and_current_editions() FROM DUAL';
    BEGIN
      DBMS_SQL.PARSE (c => c,
                      statement => stmt,
                      language_flag => DBMS_SQL.NATIVE,
                      edition => 'ora$base');
     
      DBMS_SQL.DEFINE_COLUMN (c, 1, v, 200);
      dummy := DBMS_SQL.EXECUTE_AND_FETCH (c, true);
      DBMS_SQL.COLUMN_VALUE (c, 1, v);
      DBMS_SQL.CLOSE_CURSOR(c);
      DBMS_OUTPUT.PUT_LINE (v);
    END;
    /
    

    結果:

    Session: E2 / Current: ORA$BASE
     
    PL/SQL procedure successfully completed.

エディションのリタイア

新しいエディション(アップグレードしたアプリケーション)をすべてのユーザーが使用できるようにしたら、SYS以外のユーザーが古いエディションを使用できないようにするために、古いエディション(元のアプリケーション)をリタイアさせます。

注意:

古いエディションがデータベースのデフォルト・エディションである場合は、この古いエディションをリタイアさせる前に、別のエディションをデフォルトにします。

ALTER DATABASE DEFAULT EDITION = edition_name

エディションをリタイアさせるには、このエディションに対するUSE権限を、すべての権限受領者から取り消します。権限受領者のリストを表示するには、次の問合せを使用します。ここで、eには削除するエディションの名前が入ります。

SELECT GRANTEE, PRIVILEGE
FROM DBA_TAB_PRIVS
WHERE TABLE_NAME = :e AND TYPE = 'EDITION'
/

エディションをリタイアさせる場合、それに応じて非エディション・オブジェクトの評価エディションおよび未使用エディションを更新します。

関連項目:

エディションの削除

注意:

エディションにcrosseditionトリガーが含まれている場合は、エディションを削除する前に、「crosseditionトリガーの削除」を参照してください。

エディションを削除するには、DROP EDITION文を使用します。エディションに実オブジェクトがある場合は、実オブジェクトを削除するCASCADE句を指定する必要があります。

DROP EDITION edition CASCADE文が正常終了前に(たとえば、停電などの理由で)中断された場合、静的データ・ディクショナリ・ビュー*_EDITIONSには、editionに対するUSABLEの値がNOであることが表示されます。このように使用できないeditionに対して実行できる唯一の操作は、DROP EDITION CASCADEです。

エディションは次の場合に削除します。

  • アプリケーション・アップグレードをロールバックする必要がある場合。

  • (オプション)エディションをリタイアさせた場合。

エディションを削除できるのは、次のすべての条件に該当する場合のみです。

  • エディションがルート・エディション、またはリーフ・エディションである場合。

  • エディションは使用されていません。(つまり、セッションの現行エディションまたはセッション・エディションではない場合。)

  • このエディションが、データベースのデフォルト・エディションではない場合。

エディションがルートであり、COMPATIBLEパラメータが12.2.0以上に設定されている場合、エディションは使用不可としてマークされます。対象オブジェクトは、使用可能な子孫エディションで継承されなくなったエディション・オブジェクトです。使用不可のエディション内の各対象オブジェクトは、自動的にスケジュールされたメンテナンス・プロセスによって削除されます。使用不可のルート・エディションに残っているオブジェクトがなくなると、エディション自体が自動的に削除されます。このクリーン・アップ・プロセスが、検出された各使用禁止ルート・エディションごとに繰り返されます。ユーザーは、DBMS_EDITIONS_UTILITIES.CLEAN_UNUSABLE_EDITIONSプロシージャ(Oracle Database PL/SQLパッケージおよびタイプ・リファレンスを参照)を手動で実行することで、このプロセスをオンデマンドで実行できます。

COMPATIBLEが12.1.0以下に設定されている場合、ルート・エディションは、その子孫が継承するオブジェクトを持っている必要はありません。ルート・エディションから継承された各オブジェクトは、エディションを削除する前に、実オブジェクト化するか、明示的に削除する必要があります。

エディションがリーフの場合はリーフ内のすべてのエディション・オブジェクトが削除され、その後、文の実行が完了する前に、エディション自体も削除されます。

注意:

エディションを削除した後、次の両方の条件に該当する場合、エディション・オブジェクトに依存する非エディション・オブジェクトを再コンパイルすることはできません。

  • 非エディション・オブジェクトにADTが含まれている。

  • 非エディション・オブジェクトが依存するエディション・オブジェクトの所有者が、FORCEを使用してエディションに対して有効化されたときに、非エディション・オブジェクトが無効化されていた。

子エディションで継承オブジェクトを明示的に実オブジェクト化するには、次のようにします。

  1. 子エディションをセッション・エディションにします。

    手順は、「セッション・エディションの変更」を参照してください。

  2. COMPILEで、適切なALTER文を使用して、このオブジェクトを再コンパイルします。PL/SQLオブジェクトについては、REUSE SETTINGSも指定してください。

    たとえば、次の文ではプロシージャp1が実オブジェクト化されます。

    ALTER PROCEDURE p1 COMPILE REUSE SETTINGS
    

エディションを削除する場合、それに応じて非エディション・オブジェクトの評価エディションおよび未使用エディションを更新します。

関連項目:

エディショニング・ビュー

エディショニング・ビュー以外のビューで定義できるトリガーのタイプは、INSTEAD OFトリガーのみです。エディショニング・ビューでは、表で定義できるトリガー・タイプすべてを定義できます(ただし、crosseditionトリガー(一時トリガー)とINSTEAD OF トリガーは例外です)。このため、またエディショニング・ビューはエディション化が可能であることによって、エディショニング・ビューを使用することで、実表がエディション化されたかのように扱うことができます。ただし、アップグレードされたアプリケーションにより、新しい索引または制約が必要とされる場合、エディショニング・ビューに索引または制約を追加することはできません。これらは実表に追加する必要があります。

注意:

実表または実表上の索引を変更する場合は、非ブロック化およびブロック化のDDL文を参照してください。

エディショニング・ビューは1つの実表の列のサブセットを選択し、オプションとしてそれらの列に別名を提供します。別名を提供するとき、エディショニング・ビューは物理列名(実表で使用される)を論理列名(アプリケーションで使用される)にマップします。エディショニング・ビューは、表のAPIに似ています。

直接ではなく、エディショニング・ビュー経由で表にアクセスすることに対するパフォーマンス・ペナルティはありません。つまり、SQL SELECTINSERTUPDATEDELETE、またはMERGE文で1つ以上のエディショニング・ビューが1回以上使用されているときに、必要に応じて、エディショニング・ビューの名前を実表の名前で置き換え、列名を調整した場合でも、パフォーマンスは変わりません。

静的データ・ディクショナリ・ビュー*_EDITIONING_VIEWSは、セッション・エディションで表示可能なデータベース内のすべてのエディショニング・ビューを示します。*_EDITIONING_VIEWS_AEは、すべてのエディションにおけるデータベース内のすべてのエディショニング・ビューのすべての実オブジェクトを示します。

トピック:

エディショニング・ビューの作成

エディショニング・ビューを作成する前に、所有者がエディション対応であり、スキーマ・オブジェクト・タイプVIEWが所有者でエディション対応である必要があります。

エディショニング・ビューを作成するには、SQL文CREATE VIEWをキーワードEDITIONINGとともに使用します。エディショニング・ビューを読取り専用にするには、WITH READ ONLYを指定します。読取り/書込みにするにはWITH READ ONLYを省略します。NONEDITIONABLEは指定しないでください。指定すると、エラーが発生します。

エディショニング・ビューが読取り専用の場合、未変更アプリケーションのユーザーが実表のデータを見ることはできますが、変更することはできません。この実表は準可用性を備えています。準可用性を利用できるのは、ユーザーが読むだけで変更しない、オンライン・ディクショナリなどのアプリケーションです。実表にcrosseditionトリガーを定義しない場合は、エディショニング・ビューを読取り専用にします。

エディショニング・ビューが読取り/書込みの場合、未変更アプリケーションのユーザーが、実表のデータを見ることも変更することもできます。この実表は最大可用性を備えています。最大可用性が必要となるのは、ユーザーが注文を発行するオンライン・ストアなどのアプリケーションです。実表にcrosseditionトリガーを定義する場合は、エディショニング・ビューを読取り/書込みにします。

エディショニング・ビューは、実表からの列のサブセットの選択と列の別名提供の他にも機能を実行する必要があるため、エディショニング・ビューを作成するCREATE VIEW文には制限があります。制限に違反すると、FORCEを指定していてもビューの作成が失敗します。

関連項目:

パーティション拡張エディショニング・ビュー名

パーティション表に定義されているエディショニング・ビューには、パーティション拡張名を付けることができます。この名前は、実表のパーティションおよびサブパーティションを示すパーティション名とサブパーティション名を含みます。

パーティション拡張表名に対応するデータ操作言語(DML)は、パーティション拡張エディショニング・ビュー名にも対応します。次の文が対応しています。

  • DELETE

  • INSERT

  • SELECT

  • UPDATE

関連項目:

パーティション表の参照の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

エディショニング・ビューの書込み可能性の変更

既存のエディショニング・ビューを読取り専用から読取り/書込みに変更するには、SQL文ALTER VIEW READ WRITEを使用します。既存のエディショニング・ビューを読取り/書込みから読取り専用に変更するには、SQL文ALTER VIEW READ ONLYを使用します。

関連項目:

ALTER VIEW文の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

エディショニング・ビューの置換

エディショニング・ビューを置換するには、SQL文CREATE VIEWOR REPLACE句およびキーワードEDITIONINGとともに使用します。

エディショニング・ビューを置換できるのは別のエディショニング・ビューのみです。置換対象のエディショニング・ビューに定義されているトリガーはすべて保持されます。

削除または名前変更された実表

エディショニング・ビューの定義が基づいている実表を削除したり名前を変更したりしても、エディショニング・ビューは削除されませんが、エディショニング・ビューとその依存オブジェクトが無効になります。ただし、エディショニング・ビューに定義されているトリガーはすべて保持されます。

実表への索引と制約の追加

アップグレードされたアプリケーションにより、新しい索引または制約が必要とされる場合は、これらを実表に追加する必要があります。これらをエディショニング・ビューに追加することはできません。

新しい索引が古いエディション(元のアプリケーション)に悪い影響を与える場合は、これらを非表示にします。新しい索引の使用が必要なcrosseditionトリガーで、これらをINDEXヒントに指定します。

すべてのユーザーがアップグレードされたアプリケーションのみを使用している場合は、次のようにします。

  • 新しい索引を使用しているのがcrosseditionトリガーのみである場合は、これらの索引を削除します。

  • アップグレードされたアプリケーションが新しい索引で便利である場合は、これらを表示します。

SQLオプティマイザ索引ヒント

SQLオプティマイザ索引ヒントは、索引を構成する列の論理名を使用して指定されます。論理列名を使用してエディショニング・ビューに指定されたSQLオプティマイザ索引ヒントは、実表の対応する物理列の索引にマップする必要があります。

関連項目:

ヒントの使用方法の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

crosseditionトリガー

crosseditionトリガーと非crosseditionトリガーの最も大きな違いは、エディションとの相互作用の方法です。crosseditionトリガーは、それが実であるエディションにのみ表示されます。子孫エディションでは表示されません。forward crosseditionトリガーは、データを古いエディションが使用していた列から、新しいエディションが使用している列に移動します。reverse crosseditionトリガーは逆方向へデータを移動します。

この他の重要な違いは次のとおりです。

  • crosseditionトリガーは、他の表に定義されたトリガーに対して並べ替えることができますが、非crosseditionトリガーは同じ表に定義されたトリガーに対してのみ並べ替えることができます。

  • crosseditionトリガーは一時的に使用します。構成を変更した表をすべてのユーザーが使用できるようにした後で削除します。

トピック:

forward crosseditionトリガー

アップグレード後のエディションでDML変更を表に行うと、新しい列または新しい表のみに書き込まれ、アップグレード前(祖先)エディションのユーザーが読取りまたは書込みを行う可能性がある列に対しては行われません。ただし、祖先エディションのユーザーが表データを変更する場合、表示しているエディショニング・ビューがそれらの変更内容を正確に反映する必要があります。これは、forward crosseditionトリガーを使用することで実現します。

forward crosseditionトリガーはトランスフォームを定義します。これは、古い行を1つ以上の新しい行に変換するための規則です。古い行は、アップグレード前の表現に含まれるデータ行です。新しい行は、アップグレード後の表現に含まれるデータ行です。トリガーの名前はトリガー自体、およびこのトリガーにより定義された変換を表します。

reverse crosseditionトリガー

アップグレード前のエディションとアップグレード後のエディションが同時に通常使用(ホット・ロールオーバー)されている場合、reverse crosseditionトリガーを使用して、アップグレード後エディションのユーザーが表データを変更するときに、変更内容がアップグレード前エディションに正確に反映されるようにします。

crosseditionトリガーとエディションの相互作用

crosseditionトリガーと非crosseditionトリガーの最も大きな違いは、エディションとの相互作用の方法です。

ここでは、現行エディションは、トリガーを起動するDML文が実行されるエディションを指します。現行エディションがセッション・エディションと異なることがあります。

トピック:

表示可能なトリガー

エディションは、非crosseditionトリガーを他のエディション・オブジェクトと同じように継承します(「エディション・オブジェクトおよび変更時のコピー」を参照)。

エディションはcrosseditionトリガーは継承しません。crosseditionトリガーは、別のエディションで実行されるDML文に対応して起動されることもありますが、名前が表示されるのは作成されたエディションのみです。したがって、エディションでは、祖先エディションで作成されたcrosseditionトリガーの名前を再利用できます。crosseditionトリガーの名前を再利用しても、古いトリガーの起動条件は変更されません。

静的データ・ディクショナリ・ビューに示されるcrosseditionトリガーは、現行エディションの実オブジェクトです。

起動できるトリガーの種類

起動できるトリガーの種類は、トリガーするDML文のカテゴリによって異なります。

カテゴリ:

注意:

SQL INSERT文にAPPENDヒントを指定してもcrosseditionトリガーの起動を防ぐことはできません。

関連項目:

APPENDヒントの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

forward crosseditionトリガーSQL

forward crosseditionトリガーSQLは、次のいずれかの方法で実行されるSQLです。

  • forward crosseditionトリガー本体から直接起動

    forward crosseditionトリガーのローカル・サブプログラムが起動された場合のみ、このカテゴリには、起動されたサブプログラムのSQLが含まれます。

  • apply_crossedition_triggerパラメータに対してNULL以外の値を指定してDBMS_SQL.PARSEプロシージャを起動

    apply_crossedition_triggerパラメータに対して唯一有効なNULL以外の値は、forward crosseditionトリガーの非修飾名です。

forward crosseditionトリガーが別のコンパイル・ユニットに含まれるサブプログラムを起動する場合、このトリガーがapply_crossedition_triggerパラメータにNULL以外の値が指定されたDBMS_SQL.PARSEプロシージャにより起動された場合のみ、このサブプログラムのSQLがforward crosseditionトリガーSQLになります。

forward crosseditionトリガーSQLは、次の条件をすべて満たすトリガーのみ起動できます。

  • forward crosseditionトリガーである。

  • 現行エディションまたは現行エディションの子孫で作成された。

  • 実行中のforward crosseditionトリガーに明示的に後続する。

関連項目:

DBMS_SQL.PARSEプロシージャの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。

reverse crosseditionトリガーSQL

reverse crosseditionトリガーSQLは、reverse crosseditionトリガー本体から直接実行されるSQLです。reverse croseditionトリガーのローカル・サブプログラムが起動された場合のみ、このカテゴリには、起動されたサブプログラムのSQLが含まれます。

reverse crosseditionトリガーSQLは、次の条件をすべて満たすトリガーのみ起動できます。

  • reverse crosseditionトリガーである。

  • 現行エディションまたは現行エディションの先祖で作成された。

  • 実行中のreverse crosseditionトリガーよりも前に明示的に実行される。

アプリケーションSQL

アプリケーションSQLは、crosseditionトリガーSQLを除くすべてのSQLで、次のDML文が含まれます。

  • DBMS_SQLパッケージを使用してコーディングされた動的SQL DML文。

  • Javaストアド・プロシージャおよび外部プロシージャによって実行されるDML文(これらのプロシージャがCALLトリガーで起動された場合も含む)

アプリケーションSQLは、次の規則に従って、noncrosseditionトリガーとcrosseditionトリガーの両方を起動します。

トリガーの種類 トリガーの起動条件

noncrossedition

トリガーが現行エディションで表示可能かつ有効である。

forward crossedition

トリガーが現行エディションの子孫で作成された。

reverse crossedition

トリガーが現行エディションまたは現行エディションの祖先で作成された。

関連項目:

DBMS_SQLパッケージの詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。

起動順序

特定のDML文に対応してトリガーを起動するためのトリガーの条件は次のとおりです。

  • 適切な種類である

  • 選択の条件を満たしている(たとえば、DML文の種類やWHEN句)

  • 有効化されている

これらの提供を満たすトリガーの場合、起動順序は、FOLLOWSおよびPRECEDES句、トリガーの種類、およびエディションに依存します。

トピック:

FOLLOWS句およびPRECEDES句

トリガーAとBが同じタイミング・ポイントで起動されるとき、次のいずれかに該当するとAはBよりも先に起動します。

  • Aが明示的にBに先行する場合。

  • Bが明示的にAに続く場合。

この規則は次のような条件とは無関係です。

  • トリガーが有効か無効か。

  • UPDATE OF句に指定された列が変更されるかどうか。

  • WHEN句が満たされるかどうか。

  • 2つのトリガーが同じ種類のDML文(INSERTUPDATEまたはDELETE)に関連付けられているかどうか。

  • トリガーのタイミング・ポイントが重なっているかどうか。

明示的な先行または後続の関係がないトリガーの起動順序は予測できません。

トリガーの種類とエディション

トリガーを起動するDML文に関連付けられた各タイミング・ポイントでは、条件に合うトリガーが次の順序で起動されます。1から3ではFOLLOWSの関係が適用され、45ではPRECEDESの関係が適用されます。

  1. crosseditionトリガー以外のトリガー

  2. 現行エディションで作成されたforward crosseditionトリガー

  3. 現行エディションの子孫で作成されたforward crosseditionトリガー(子孫の作成順(子、孫、その子など))

  4. 現行エディションで作成されたreverse crosseditionトリガー

  5. 現行エディションの祖先で作成されたreverse crosseditionトリガー(祖先の作成と逆順(親、その親、さらにその親など))

crosseditionトリガーの実行

crosseditionトリガーは、自らが作成されたエディションを使用して実行します。crosseditionトリガーがコールするすべてのコード(パッケージ参照、PL/SQLサブプログラム・コールおよびSQL文を含む)も、crosseditionトリガーが作成されたエディションで実行します。

PL/SQLパッケージが複数のエディションで実パッケージである場合、単一セッション内であっても、パッケージの変数やその他の状態は各エディションのみで公開されます。各crosseditionトリガーおよびそれらのトリガーがコールするコードは、crosseditionトリガーが作成されたエディションを使用して実行するため、同一セッションがパッケージの複数のバージョンを同じ名前でインスタンス化することがあります。

crosseditionトリガーの作成

crosseditionトリガーを作成する前に、所有者がエディション対応であり、スキーマ・オブジェクト・タイプTRIGGERが所有者でエディション対応である必要があります。(手順は、「ユーザーに対するエディションの有効化」を参照してください。)

次の規則に注意しながらSQL文CREATE TRIGGERを使用して、crosseditionトリガーを作成します。

  • crosseditionトリガーは、ビューではなく表に定義する必要があります。

  • crosseditionトリガーには、EDITIONABLEプロパティが必要です。

  • crosseditionトリガーはDMLトリガー(単純トリガーまたは複合トリガー)であることが必要です。

    crosseditionトリガー本体でのDML文としては、静的SQL文またはネイティブ動的SQL文のいずれかを使用できます。

  • crosseditionトリガーは、REVERSEを指定しないかぎりforwardになります。(FORWARDの指定はオプションです。)

  • FOLLOWS句を使用できるのは、forward crosseditionトリガーまたは非crosseditionトリガーを作成する場合のみです。(FOLLOWS句は、作成中のトリガーが、指定したトリガーの起動後に起動することを指定します。)

  • PRECEDES句を使用できるのは、reverse crosseditionトリガーを作成する場合のみです。(PRECEDES句は、作成中のトリガーが、指定したトリガーの起動前に起動することを指定します。)

  • FOLLOWS句またはPRECEDES句に指定するトリガーは存在している必要がありますが、有効になっていなくても、正常にコンパイルされていなくてもかまいません。

  • 非crosseditionトリガーと同じく、crosseditionトリガーは、DISABLEを指定しないかぎり作成された時点で有効になっています。(ENABLEの指定はオプションです。)

    ヒント:

    crosseditionトリガーは無効な状態で作成して、正常にコンパイルされたことを確認した後で有効にします。有効な状態で作成してからコンパイルが失敗すると、既存のアプリケーションのユーザーの操作が影響を受けます。

  • crosseditionトリガー本体の操作は多重呼出し不変(操作を複数回実行するのは冗長であり、結果は変わらない)である必要があります。

関連項目:

forward crosseditionトリガー本体のコーディング

forward crosseditionトリガーの本体の操作は、予測が不可能であるため、多重呼出し不変である必要があります。

  • 古い行に対して本体が最初に実行されるコンテキスト。

    可能性は次のとおりです。

    • 祖先エディションのユーザーが、トリガー(予期せぬ変更)を起動するDML文を実行するとき

    • トリガーが定義する変換を適用するとき(古いフォーマットから新しいフォーマットに行を一括アップグレードします)

  • 本体が古い行それぞれについて何回実行されるか。

トピック:

データ変換における衝突の処理

forward crosseditionトリガーが(表の新しい列ではなく)新しい表を移入する場合、その本体は必ずデータ変換の衝突に対応します。

たとえば、新しい表のある列にUNIQUE制約が含まれるとします。予期せぬ変更によりforward crosseditionトリガーが起動され、これにより新しい表に1行挿入されます。その後、別の予期せぬ変更により、forward crosseditionトリガーが起動されるか、またはユーザーがトリガーにより定義された変換を適用します。このトリガーは新しい表への行の挿入を試行しますが、これはUNIQUE制約に違反しています。

衝突処理方法がトリガーの実行理由に応じて変わる場合、その理由はファンクションAPPLYING_CROSSEDITION_TRIGGERにより判断できます。このファンクションがトリガーの本体から直接呼び出されたときに、予期せぬ変更によりトリガーが実行されていた場合はBOOLEAN値のTRUEが返されます。また、一括での変換が適用されたためにトリガーが実行されていた場合はFALSEが返されます。(APPLYING_CROSSEDITION_TRIGGERは、パッケージDBMS_STANDARDで定義されています。これにはパラメータはありません。)これにはパラメータはありません。)

衝突を無視し、既存の行と衝突しない行を挿入するには、INSERT文にIGNORE_ROW_ON_DUPKEY_INDEXヒントを入れます。

このような衝突を無視したくはないが、これらに対応するために、衝突がどこで発生しているかを知る必要があるという場合は、INSERTまたはUPDATE文にCHANGE_DUPKEY_ERROR_INDEXヒントを入れ、索引または列のセットを指定します。その後、索引、または列のセットに一意キーの違反が発生した場合、ORA-00001のかわりにORA-38911が報告されます。ORA-38911に対する例外ハンドラを書くことができます。

注意:

ヒントの構文もありますが、IGNORE_ROW_ON_DUPKEY_INDEXおよびCHANGE_DUPKEY_ERROR_INDEXは必須です。これらはオプティマイザにより必ず使用されます。

例27-5APPLYING_CROSSEDITION_TRIGGERファンクション、およびIGNORE_ROW_ON_DUPKEY_INDEXヒントとCHANGE_DUPKEY_ERROR_INDEXヒントを使用して、データ変換の衝突に対応するcrosseditionトリガーを作成します。このトリガーはtable1の古い行をtable2の新しい行に変換します。この表を次のように作成されます。

CREATE TABLE table1 (key NUMBER, value VARCHAR2(20));

CREATE TABLE table2 (key NUMBER, value VARCHAR2(20), last_updated TIMESTAMP);
CREATE UNIQUE INDEX i2 on table2(key);

関連項目:

例27-5 データ変換の衝突に対応するcrosseditionトリガー

CREATE OR REPLACE TRIGGER trigger1
  BEFORE INSERT OR UPDATE ON table1
  FOR EACH ROW
  CROSSEDITION
DECLARE
  row_already_present  EXCEPTION;
  PRAGMA EXCEPTION_INIT(row_already_present, -38911);
BEGIN
  IF APPLYING_CROSSEDITION_TRIGGER THEN
    /* The trigger is running because of applying the transform.
       If the old edition of the app has already caused this trigger
          to insert a row, we do not modify the row as part of applying
          the transform. Therefore, insert the new row into table2 only if
          it is not already there. */
    INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(table2(key)) */
    INTO table2
    VALUES(:new.key, :new.value, to_date('1900-01-01', 'YYYY-MM-DD'));
  ELSE
     /* The trigger is running because of a serendipitous change.
          If no previous run of the trigger has already inserted
          the corresponding row into table2, insert the new row;
          otherwise, update the previously inserted row. */
    BEGIN
      INSERT /*+ CHANGE_DUPKEY_ERROR_INDEX(table2(key)) */
      INTO table2
      VALUES(:new.key, :new.value, SYSTIMESTAMP);
    EXCEPTION WHEN row_already_present THEN
      UPDATE table2
      SET value = :new.value, last_updated = SYSTIMESTAMP
      WHERE key = :new.key;
    END;
  END IF;
END;
/
他の表への変更の処理

トリガーが定義された表以外の表を変更する明示的なSQL文がforward crosseditionトリガーの本体に含まれ、それらの表の行にトリガーが定義された表の行との1対1の対応がない場合、次の状況を正しく処理するためのロック・メカニズムを本体コードに実装する必要があります。

  • 祖先エディションの複数のユーザーが、トリガーの定義されている表に対するDML文を同時に発行する状況。

  • 祖先エディションのユーザーのうち、少なくとも1人が、トリガーの定義されている表に対するDML文を発行する状況。

アップグレード前の表現をアップグレード後の表現に変換

アップグレードしているアプリケーションを構成するデータベース・オブジェクトを(新しいエディションで)再定義した後、アプリケーション・データを(古いエディションで)アップグレード前の表現から(新しいエディションで)アップグレード後の表現に変換する必要があります。この変換の規則はトランスフォームと呼ばれ、これらはforward crosseditionトリガーにより定義されます。

古い行の一部は、予期せぬ変更、つまり、forward crosseditionトリガーが起動したアップグレード前のアプリケーションのユーザーが行った変更により、新しい行にトランスフォームされている可能性があります。しかし、予期せぬ変更によりトランスフォームされなかった行はすべてアップグレード前の表現のままです。古い行がすべて新しい行に確実にトランスフォームされるようにするには、アプリケーション・データに格納されている表で定義したトランスフォームを適用する必要があります。

トランスフォームを適用する方法には次の3通りがあります。

  • トランスフォームを定義しているトリガーを、表のすべての行に対して一度に1行ずつ起動します。

  • トリガーを起動するかわりに、トリガーで行われる内容をより速く処理するSQL文を実行し、そのトリガーに続くトリガーがあれば起動します。

    表全体を置換した場合、または新しい表を作成した場合は、最初の方法より2番目の方法をお薦めします。

  • プロシージャDBMS_EDITIONS_UTILITIES.SET_NULL_COLUMN_VALUES_TO_EXPRを起動し、メタデータ操作を使用して、トランスフォームを新規列に適用します。

    この3番目の方法の場合、インストール時間は最も短くなりますが、トランスフォームを表す式に関する制限があり、メタデータが実データによって置換されるまで新規列の問合せが遅くなります。

    次の場所において、メタデータは実データによって置換されます。

    • 更新される個別列要素内。

    • オンライン表再定義を使用して表が圧縮されるすべての列要素内。

トランスフォームを適用する最初の2つの方法の場合、DBMS_SQL.PARSEプロシージャ、またはDBMS_PARALLEL_EXECUTEパッケージのサブプログラムを起動します。大量のデータがある場合は2番目の方法をお薦めします。このサブプログラムを使用すると、大容量の表のデータを並列で増分的に更新することができます。これは次の2つのステップで行われます。

  1. 表の行をグループ化して小さなチャンクに分けます。
  2. 必要なUPDATE文を並列でチャンクに適用し、1チャンクの処理が終了するたびにコミットします。

この利点は次のとおりです。

  • 表全体のロックではなく、相対的に短い時間で一度に1セットの行のみをロックする。

  • 操作全体が完了する前に問題が発生してもそれまでに処理した内容が失われない。

DBMS_SQL.PARSEプロシージャとDBMS_PARALLEL_EXECUTEサブプログラムの両方で、apply_crossedition_triggerfire_apply_triggerおよびsql_stmtの実際のパラメータ値は次に示すように同じです。

  • apply_crossedition_triggerには、適用されるトランスフォームを定義するforward crosseditionトリガーの名前を指定します。

  • 表のすべての行に対して一度に1行ずつトリガーを起動するには、次のようにします。

    • fire_apply_triggerの値にTRUEを指定します。

    • sql_stmtには、起動するforward crosseditionトリガーの選択以外に重要な影響を及ぼさないSQL文を指定します。たとえば、一部の列を各行の既存の値に設定するUPDATE文を指定します。

  • トリガーで行われる内容を処理するSQL文を実行し、そのトリガーに続くトリガーがあれば起動します。

    • fire_apply_triggerの値にFALSEを指定します。

    • sql_stmtには、forward crosseditionトリガーの処理内容をより速く行うSQL文を指定します。たとえば、1つ以上のPL/SQLサブプログラムをコールするPL/SQL無名ブロックを指定します。

関連項目:

更新内容の消失の防止

トランスフォームの適用中に更新内容が消失するのを防ぐには、次の手順を使用します。

  1. crosseditionトリガーを有効化します。
  2. 影響を受ける表への保留中の変更がコミットまたはロールバックされるまで待機します。

    DBMS_UTILITY.WAIT_ON_PENDING_DMLプロシージャを使用します。

  3. トランスフォームを適用します。

注意:

このシナリオでは、forward crosseditionトリガーが変更するのはそれが定義された表のみですが、リスクを説明するには十分です。crosseditionトリガーがまだ有効になっていないときに、セッション1がUPDATE文を表に対して発行し、次にセッション2がcrosseditionトリガーを有効にし、すぐにトランスフォームを適用するとします。

セッション1とセッション2の両方が同じ行(行n)を変更しようとすると競合状態が発生する可能性があります。どちらのセッションが先に行nに到達するかは運次第です。最初に到達したセッションがその変更をコミットしてロックを解放するまで、2番目に行nに到達したセッションは待機する必要があるとしても、両方の更新は成功します。

問題は、セッション2が競合に勝った場合に起こります。そのSQL文はトリガーが有効になった後にコンパイルされたため、その文を実装するプログラムはトリガー・アクションも実装します。そのため、目的のアップグレード後の列の値は列nに設定されます。ここでセッション1が行nに到達しました。このSQL文はトリガーが有効になる前にコンパイルされたため、この文を実装するプログラムはトリガー・アクションを実装しません。そのため、セッション2がアップグレード後の列に設定した値は変更されず、セッション1が行nを更新する前のソース列の値を反映します。つまり、セッション1の更新の目的の副作用が消失します。

関連項目:

DBMS_UTILITY.WAIT_ON_PENDING_DMLプロシージャの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。

crosseditionトリガーの削除

crosseditionトリガーを削除するには、DROP TRIGGER文を使用します。また、DROP EDITION文でCASCADE句を使用して、これらが実であるエディションを削除することにより、crosseditionトリガーを削除できます。

crosseditionトリガーは次の場合に削除します。

  • アプリケーション・アップグレードをロールバックしている(アップグレード後のエディションを削除している)場合。

    アップグレード後のエディションを削除する前に、新しい列の制約をすべて無効化、または削除する必要があります。

  • アプリケーションのアップグレードが完了し、すべてのユーザーがアップグレード後のエディションを使用できるようにしている場合。

    すべてのセッションでアップグレード後のエディションが使用されている場合は、forward crosseditionトリガーを削除できます。ただし、reverse crosseditionトリガーを削除する前に、古い列の制約をすべて無効化、または削除する必要があります。

制約を無効化または削除するには、ALTER TABLE文にDISABLE CONSTRAINTまたはDROP CONSTRAINT句を付けて使用します。

関連項目:

EBR機能に関する情報の表示

トピック:

エディションに関する情報の表示

表27-1は、エディションに関する情報を表示する静的データ・ディクショナリ・ビューについて簡単に説明しています。

表27-1 エディション情報を含む*_ディクショナリ・ビュー

ビュー 説明:

*_EDITIONS

データベースのすべてのエディションを示します。

*_EDITION_COMMENTS

データベースのすべてのエディションに関連付けられたコメントを示します。

*_EDITIONED_TYPES

デフォルトで各スキーマ内でエディション化されるスキーマ・オブジェクト・タイプをリストします。

*_OBJECTS

現行エディションで表示可能なデータベースのすべてのオブジェクトを示します。このビューには、オブジェクトごとに、エディション対応であるかどうかが示されます。

*_OBJECTS_AE

すべてのエディションにおけるデータベース内のすべてのオブジェクトを示します。このビューには、オブジェクトごとに、エディション対応であるかどうかが示されます。

*_ERRORS

現行エディションのデータベース内のすべてのエラーを示します。

*_ERRORS_AE

すべてのエディションのデータベース内のすべてのエラーを示します。

*_USERS

データベースのすべてのユーザーを示します。エディションが有効になっているユーザーを表示するときに役立ちます。

*_SERVICES

データベースのすべてのサービスを示します。EDITIONS列には、デフォルトの初期現行エディションが示されます。

*_MVIEWS

すべてのマテリアライズド・ビューを示します。マテリアライズド・ビューがエディション・オブジェクトを参照している場合、このビューには、評価エディション、およびマテリアライズド・ビューが問合せリライトに対して適格であるエディションの範囲が示されます。

*_TAB_COLS

すべての表、ビューおよびクラスタのすべての列を示します。このビューには、仮想列ごとに評価エディションと使用可能な範囲が示されます。

注意:

*_OBJECTSおよび*_OBJECTS_AEに含まれる依存オブジェクトが、表26-2の操作によって無効化されるのは、次のいずれかの後のみです。

  • オブジェクトの参照(コンパイル中または実行中)

  • DBMS_UTILITY.COMPILE_SCHEMAの呼出し

  • UTL_RECOMPサブプログラムの起動

関連項目:

エディションニング・ビューに関する情報の表示

表27-2は、エディショニング・ビューに関する情報を表示する静的データ・ディクショナリ・ビューについて簡単に説明しています。

表27-2 エディショニング・ビュー情報を含む*_ディクショナリ・ビュー

ビュー 説明:

*_VIEWS

エディショニング・ビューを含む、現行エディションで表示可能なデータベースのすべてのビューを示します。

*_EDITIONING_VIEWS

現行エディションで表示可能なデータベースのすべてのエディショニング・ビューを示します。エディショニング・ビューと実表の関係を表示するときに役立ちます。*_OBJECTS_AEと結合すると、さらに情報を得ることができます。

*_EDITIONING_VIEWS_AE

すべてのエディションにおけるデータベース内のすべてのエディショニング・ビューのすべての実オブジェクトを示します。

*_EDITIONING_VIEW_COLS

現行エディションで表示可能なデータベースのすべてのエディショニング・ビューの列を示します。エディショニング・ビューの列とマッピング先の表の列との関係を表示するときに役立ちます。*_OBJECTS_AEまたは*_TAB_COL(あるいは両方)と結合すると、さらに情報を得ることができます。

*_EDITIONING_VIEW_COLS_AE

すべてのエディションのデータベースにあるすべてのエディショニング・ビューの列を示します。

*_EDITIONING_VIEWSの各行は、*_VIEWSの1つの行と厳密に一致します。EDITIONING_VIEW = 'Y'*_VIEWSの各行は、*_EDITIONING_VIEWSの1つの行と厳密に一致します。したがって、次の例のWHERE句は冗長です。

SELECT ...
  FROM DBA_EDITIONING_VIEWS INNER JOIN DBA_VIEWS
  USING (OWNER, VIEW_NAME)
  WHERE EDITIONING_VIEW = 'Y'
  AND ...

*_EDITIONING_VIEWSの行と一致する*_VIEWSの行は、定義によりEDITIONING_VIEW = 'Y'を満たします。反対に、EDITIONING_VIEW = 'N'*_VIEWSの行に対応する行は*_ EDITIONING_VIEWSにはありません。

関連項目:

特定のビューの詳細は、『Oracle Databaseリファレンス』を参照してください。

crosseditionトリガーに関する情報の表示

トリガーの情報を表示する静的データ・ディクショナリ・ビューは、『Oracle Databaseリファレンス』を参照してください。静的データ・ディクショナリ・ビューに示されるcrosseditionトリガーは、現行エディションの実オブジェクトです。

実行される一連のcrosseditionトリガーが異なる場合、子カーソルを共有することはできません。動的パフォーマンス・ビューV$SQL_SHARED_CURSORおよびGV$SQL_SHARED_CURSORには、これに該当するかどうかを示すCROSSEDITION_TRIGGER_MISMATCH列があります。

関連項目:

V$SQL_SHARED_CURSORの詳細は、『Oracle Databaseリファレンス』を参照してください。

アプリケーションをアップグレードするためのEBRの使用

EBRを使用して、アプリケーションをオンラインでアップグレードするには、まず、アプリケーションを準備する必要があります。

  1. アプリケーション・ユーザーおよび適切なスキーマ・オブジェクト・タイプをスキーマ内でエディション対応にします。

    エディショニング・ビューを作成(次のステップ)するスキーマでは、タイプVIEWはエディション対応である必要があります。

    手順は、「ユーザーに対するエディションの有効化」を参照してください。

  2. エディショニング・ビューを使用するようにアプリケーションを準備します。

エディショニング・ビューを表示し、EBRを使用して、アプリケーションをオンラインで必要な回数、アップグレードすることができます。アップグレードのたびに、次のようにしてください。

アプリケーションでのエディショニング・ビューの使用準備

1つ以上の表を使用するアプリケーションでは、エディショニング・ビューで各表がカバーされる必要があります。エディショニング・ビューは、次のすべての記述が正しい場合にのみ、表をカバーします。

  • アプリケーション内の通常オブジェクトはすべて、エディショニング・ビューを通じてのみ、表を参照できます。(通常オブジェクトは、エディショニング・ビューまたはcrosseditionトリガー以外のすべてのオブジェクトです。エディショニング・ビューとcrosseditionトリガーは表を参照する必要があります。)

  • アプリケーション・ユーザーは、表ではなく、エディショニング・ビューに対してのみオブジェクト権限を付与されます。

  • 仮想プライベート・データベース(VPD)ポリシーは、表ではなく、エディショニング・ビューにのみアタッチされます。(日常的な監査、およびファイングレイン監査(FGA)ポリシーは、表にのみアタッチされます。)

エディショニング・ビューが実オブジェクト化された場合、VPDポリシーのコピーは実オブジェクト化されたエディショニング・ビューにアタッチされます。(ポリシーは名前と、アタッチ先オブジェクトにより一意に識別されます。)ポリシー・ファンクションも実オブジェクト化されている場合、このポリシーのコピーは実オブジェクト化されたポリシー・ファンクションを使用します。それ以外の場合は元のポリシー・ファンクションを使用します。

VPDポリシーを示す静的なデータ・ディクショナリ・ビュー*_POLICIESは、エディションに応じて、異なる結果を表示することができます。

関連項目:

既存のアプリケーションがエディショニング・ビューを使用していない場合は、使用する各表に対して次の手順を実行して、エディショニング・ビューを使用できるようにアプリケーションを準備します。

  1. 表に新しい名前を付けます(現在の表名をエディショニング・ビューに付けるためです)。

    新しい名前は、元の名前に関連したものとし、変更履歴を示すようにしてください。たとえば、元の表名がDataの場合、新しい表名をData_1とすることができます。

  2. (オプション)表の各列に新しい名前を付けます。

    このときも、新しい名前は、元の名前に関連したものとし、変更履歴を示すようにしてください。たとえば、NameおよびNumberName_1およびNumber_1のように変更できます。

    名前を変更した列に依存するトリガーはここで無効になります。詳細は、表26-2ALTER TABLE table RENAME columnの項目を参照してください。

  3. エディショニング・ビューを作成し、表の元の名前を付けます。

    手順は、「エディショニング・ビューの作成」を参照してください。

    エディショニング・ビューには表の元の名前が付けられるため、その表名を参照しているオブジェクトがエディショニング・ビューを参照するようになります。

  4. トリガーが表に定義されている場合は、トリガーを削除してから、作成時に使用したコードを再実行します。

    こうすることで、表に定義されていたトリガーが、エディショニング・ビューに対して定義されます。

  5. VPDポリシーが表にアタッチされている場合は、このポリシーとポリシー・ファンクションを削除してから、作成時に使用したコードを再実行します。

    これにより、表にアタッチされていたVPDポリシーが、エディショニング・ビューにアタッチされます。

  6. すべてのアプリケーション・ユーザーから、表に対するすべてのオブジェクト権限を取り消します。

    表に対し、どのアプリケーション・ユーザーがどのオブジェクト権限を持っているかを確認するには、次の問合せを使用します。

    SELECT GRANTEE, PRIVILEGE
    FROM DBA_TAB_PRIVS
    WHERE TABLE_NAME='table_name';
    
  7. ステップ6で取り消された権限すべてについて、エディショニング・ビューで同じ権限を付与します。
  8. 表を参照するプライベート・シノニムを所有するユーザーごとに、タイプSYNONYMがスキーマ内でエディション対応であるよう指定し、エディションを有効化します(詳細は、「ユーザーに対するエディションの有効化」を参照)。
  9. 表を参照するプライベート・シノニムの所有者に、これらのシノニムの再作成が必要であることを通知します。

エディションのみを使用するEBRの手順

次の手順は、再定義するすべてのオブジェクトがエディション化(定義は「エディション・オブジェクトと非エディション・オブジェクト」を参照)されている場合のみ使用します。表はエディション・オブジェクトではありません。

  1. 新しいエディションを作成します。

    手順は、「エディションの作成」を参照してください。

  2. 新しいエディションをセッション・エディションにします。

    手順は、「セッション・エディションの変更」を参照してください。

  3. アプリケーションのエディション・オブジェクトに必要な変更を行います。
  4. すべてのオブジェクトが有効であることを確認します。

    静的データ・ディクショナリ*_OBJECTS_AEを問い合せます。これは、すべてのエディションにおけるデータベース内のすべての実オブジェクトを示します。無効オブジェクトが残っている場合は、任意のUTL_RECOMPサブプログラム(『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照)を使用して再コンパイルします。

  5. 変更内容が意図したように機能していることを確認します。

    機能している場合は、ステップ6に進みます。

    そうでない場合は、さらに変更を続ける(ステップ3に戻る)か、またはアプリケーション・アップグレードをロールバックします(ステップについては、「アプリケーション・アップグレードのロールバック」を参照)。

  6. 新しいエディション(アップグレードされたアプリケーション)をすべてのユーザーに対して使用可能にします。
  7. 古いエディション(元のアプリケーション)をリタイアさせ、SYS以外のすべてのユーザーがアップグレードされたアプリケーションのみを使用するようにします。

    手順は、「エディションのリタイア」を参照してください。

    例27-6は、ここで説明した手順を使用して、非常に単純なPL/SQLプロシージャを変更する方法を示します。

例27-6 非常に単純なプロシージャのEBR

  1. この例で使用するPL/SQLプロシージャを作成します。

    CREATE OR REPLACE PROCEDURE hello IS
    BEGIN
      DBMS_OUTPUT.PUT_LINE('Hello, edition 1.');
    END hello;
    /
    
  2. PL/SQLプロシージャを起動します。

    BEGIN hello(); END;
    /
    

    結果:

    Hello, edition 1.
     
    PL/SQL procedure successfully completed.
    
  3. プロシージャのEBRを実行します。

    1. 新しいエディションを作成します。

      CREATE EDITION e2 AS CHILD OF ora$base;
      

      結果:

      Edition created.
      
    2. 新しいエディションをセッション・エディションにします。

      ALTER SESSION SET EDITION = e2;
      

      結果:

      Session altered.
      
    3. プロシージャを変更します。

      CREATE OR REPLACE PROCEDURE hello IS
      BEGIN
        DBMS_OUTPUT.PUT_LINE('Hello, edition 2.');
      END hello;
      /
      

      結果:

      Procedure created.
      
    4. 変更内容が意図したように機能していることを確認します。

      BEGIN hello(); END;
      /
      

      結果:

      Hello, edition 2.
      PL/SQL procedure successfully completed.
      
    5. すべてのユーザーが新しいエディションを使用できるようにします(システム権限が必要です)。

      ALTER DATABASE DEFAULT EDITION = e2;
      
    6. 古いエディションをリタイアさせます(システム権限が必要です)。

      権限受領者のリストを表示します。

      SELECT GRANTEE, PRIVILEGE
      FROM DBA_TAB_PRIVS
      WHERE TABLE_NAME = UPPER('ora$base')
      /
      

      結果:

      GRANTEE                        PRIVILEGE
      ------------------------------ ---------
      PUBLIC                         USE
       
      1 row selected.
      

      すべての権限受領者について、古いエディションの使用を取り消します。

      REVOKE USE ON EDITION ora$base FROM PUBLIC;

エディショニング・ビューを使用するEBRの手順

1つ以上の表の構造を変更するとき、その間に他のユーザーがそれらの表のデータを変更できる必要がない場合のみ、次の手順を使用します。

  1. 新しいエディションを作成します。

    手順は、「エディションの作成」を参照してください。

  2. 新しいエディションをセッション・エディションにします。

    手順は、「セッション・エディションの変更」を参照してください。

  3. 新しいエディションで、エディショニング・ビューが読取り専用の場合は、読取り/書込みに変更します。
  4. 新しいエディションを除くすべてのエディションで、エディショニング・ビューを読取り専用にします。
  5. アプリケーションのオブジェクトに必要な変更を行います。
  6. すべてのオブジェクトが有効であることを確認します。

    静的データ・ディクショナリ*_OBJECTS_AEを問い合せます。これは、すべてのエディションにおけるデータベース内のすべての実オブジェクトを示します。無効オブジェクトが残っている場合は、任意のUTL_RECOMPサブプログラム(『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照)を使用して再コンパイルします。

  7. 変更内容が意図したように機能していることを確認します。

    機能している場合は、ステップ8に進みます。

    そうでない場合は、さらに変更を続ける(ステップ 5に戻る)か、またはアプリケーション・アップグレードをロールバックします(ステップについては、「アプリケーション・アップグレードのロールバック」を参照)。

  8. アップグレードされたアプリケーションをすべてのユーザーに対して使用可能にします。
  9. 古いエディション(元のアプリケーション)をリタイアさせ、SYS以外のすべてのユーザーがアップグレードされたアプリケーションのみを使用するようにします。

    手順は、「エディションのリタイア」を参照してください。

crosseditionトリガーを使用するEBRの手順

1つ以上の表の構造を変更するとき、その間に他のユーザーがそれらの表のデータを変更する必要がある場合のみ、次の手順を使用します。

  1. 新しいエディションを作成します。

    手順は、「エディションの作成」を参照してください。

  2. 新しいエディションをセッション・エディションにします。

    手順は、「セッション・エディションの変更」を参照してください。

  3. アプリケーションのオブジェクトに永続的な変更を行います。

    たとえば、表に新しい列を追加し、新しい永続サブプログラムを作成します。

    ここで、変更したオブジェクトに依存するオブジェクトが無効になることがあります。詳細については、表26-2を参照してください。

  4. すべてのオブジェクトが有効であることを確認します。

    静的データ・ディクショナリ*_OBJECTS_AEを問い合せます。これは、すべてのエディションにおけるデータベース内のすべての実オブジェクトを示します。無効オブジェクトが残っている場合は、任意のUTL_RECOMPサブプログラム(『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照)を使用して再コンパイルします。

  5. 一時オブジェクト、すなわちcrosseditionトリガー(無効状態)とトリガーで必要なサブプログラムを作成します。

    手順は、「crosseditionトリガーの作成」を参照してください。

    reverse crosseditionトリガーが必要になるのは、ステップ10(オプション)を実行する場合のみです。

  6. crosseditionトリガーが正常にコンパイルされたら、crosseditionトリガーを有効にします。

    ALTER TRIGGER文にENABLEオプションを付けて使用します。この文の詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。

  7. 保留中の変更がコミットまたはロールバックされるまで待機します。

    プロシージャDBMS_UTILITY.WAIT_ON_PENDING_DMLを使用します。このプロシージャの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。

  8. トランスフォームを適用します。

    手順については、「アップグレード前の表現をアップグレード後の表現に変換」を参照してください。

    注意:

    このステップが既存の行を処理した後で、祖先エディションのユーザーが同じ行のデータを更新、挿入または削除するかどうかを予測することはできません。

  9. 変更内容が意図したように機能していることを確認します。

    機能している場合は、ステップ10に進みます。

    そうでない場合は、さらに変更を続ける(ステップ 3に戻る)か、またはアプリケーション・アップグレードをロールバックします(ステップについては、「アプリケーション・アップグレードのロールバック」を参照)。

  10. (オプション)セッション・エディションのUSE権限を、アップグレードしたアプリケーションの初期のユーザーに付与します。
  11. アップグレードされたアプリケーションをすべてのユーザーに対して使用可能にします。
  12. 制約を無効化、または削除してから、crosseditionトリガーを削除します。

    手順は、「crosseditionトリガーの削除」を参照してください。

  13. 古いエディション(元のアプリケーション)をリタイアさせ、SYS以外のすべてのユーザーがアップグレードされたアプリケーションのみを使用するようにします。

    手順は、「エディションのリタイア」を参照してください。

アプリケーション・アップグレードのロールバック

アプリケーション・アップグレードをロールバックするには、次のようにします。

  1. セッション・エディションを、アップグレード用に作成した新しいエディション以外のものに変更します。

    手順は、「セッション・エディションの変更」を参照してください。

  2. アップグレード用に作成した新しいエディションを削除します。

    手順は、「エディションの削除」を参照してください。

  3. アップグレード中に、新しい表の列を作成した場合、これらの列が占めていた領域を再利用します(手順については、「使用されていない表の列が占める領域の再利用」を参照)。

使用されていない表の列が占める領域の再利用

新しい表の列を作成したアップグレードをロールバックする場合

未使用の列が占めている領域を再利用するには、次のようにします。

  1. 未使用の列の値をNULLに設定します。

    この操作を行っている間に、他のユーザーをロックアウトしてしまわないようにするには、DBMS_PARALLEL_EXECUTEプロシージャを使用します(『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照)。

  2. 未使用の列をUNUSEDに設定します。

    ALTER TABLE文(『Oracle Database SQL言語リファレンス』を参照)をSET UNUSED句(『Oracle Database SQL言語リファレンス』を参照)とともに使用します。

  3. 表を縮小します。

    ALTER TABLE文(『Oracle Database SQL言語リファレンス』を参照)をSHRINK SPACE句(『Oracle Database SQL言語リファレンス』を参照)とともに使用します。

例: アプリケーションをアップグレードするためのEBRの使用

この例は、エディション、エディショニング・ビュー、forward crosseditionトリガーおよびreverse crosseditionトリガーを使用します。

トピック:

注意:

アプリケーションのアップグレードにEBRを使用する前に、このアプリケーションで使用されるスキーマすべてについてエディションを有効化する必要があります。手順は、「ユーザーに対するエディションの有効化」を参照してください。

既存のアプリケーション

既存のアプリケーション(アップグレード対象のアプリケーション)は、トリガーが定義された1つの表で構成されています。

既存のアプリケーションにはトリガーがあり、チェックすることができます。次の例では、既存のアプリケーションを示します。

例: 既存アプリケーションが作成された方法

このアプリケーションは例27-7に従って作成されたものです。

例27-7 既存のアプリケーションの作成

  1. 表を作成します。

    CREATE TABLE Contacts(
      ID            NUMBER(6,0) CONSTRAINT Contacts_PK PRIMARY KEY,
      Name          VARCHAR2(47),
      Phone_Number  VARCHAR2(20)
    );
    
  2. 表にデータを移入します(例は示されていません)。

  3. 表にトリガーを作成する準備をします。

    ALTER TABLE Contacts ENABLE VALIDATE CONSTRAINT Contacts_PK;
     
    DECLARE Max_ID INTEGER;
    BEGIN
      SELECT MAX(ID) INTO Max_ID FROM Contacts;
      EXECUTE IMMEDIATE '
        CREATE SEQUENCE Contacts_Seq
          START WITH '||To_Char(Max_ID + 1);
    END;
    /
    
  4. トリガーを作成します。

    CREATE TRIGGER Contacts_BI
      BEFORE INSERT ON Contacts FOR EACH ROW
    BEGIN
      :NEW.ID := Contacts_Seq.NEXTVAL;
    END;
    /
    
例: 既存表のデータ表示

例27-8は、データ移入後の表Contactsを示しています。

例27-8 既存表のデータ表示

問合せ:

SELECT * FROM Contacts
ORDER BY Name;
 

結果:

        ID NAME                                            PHONE_NUMBER
---------- ----------------------------------------------- --------------------
       174 Abel, Ellen                                     011.44.1644.429267
       166 Ande, Sundar                                    011.44.1346.629268
       130 Atkinson, Mozhe                                 650.124.6234
       105 Austin, David                                   590.423.4569
       204 Baer, Hermann                                   515.123.8888
       116 Baida, Shelli                                   515.127.4563
       167 Banda, Amit                                     011.44.1346.729268
       172 Bates, Elizabeth                                011.44.1343.529268
       192 Bell, Sarah                                     650.501.1876
       151 Bernstein, David                                011.44.1344.345268
       129 Bissot, Laura                                   650.124.5234
       169 Bloom, Harrison                                 011.44.1343.829268
       185 Bull, Alexis                                    650.509.2876
       187 Cabrio, Anthony                                 650.509.4876
       148 Cambrault, Gerald                               011.44.1344.619268
       154 Cambrault, Nanette                              011.44.1344.987668
       110 Chen, John                                      515.124.4269
       ...
       120 Weiss, Matthew                                  650.123.1234
       200 Whalen, Jennifer                                515.123.4444
       149 Zlotkey, Eleni                                  011.44.1344.429018

107 rows selected.

Contactsを再定義する必要があるとします。Name列をFirst_Name列とLast_Name列で置換し、Country_Code列を追加します。また、この構造変更を行う際に、他のユーザーがContactsのデータを変更できることが必要です。

EBRのすべての機能が必要になります。つまり、エディション(常に必要)、エディショニング・ビュー(表を再定義するため)、およびcrosseditionトリガー(表の再定義中に他のユーザーが表のデータを変更する必要があるため)です。

アプリケーションでのエディショニング・ビューの使用準備

例27-9は、新しいエディションでエディショニング・ビューを作成する方法を示します。Contacts表を再定義している間、エディショニング・ビューを使用して他のユーザーがその表にアクセスします。

例27-9 既存の表のエディショニング・ビューの作成

  1. 表に新しい名前を付けます(現在の表名をエディショニング・ビューに付けるためです)。

    ALTER TABLE Contacts RENAME TO Contacts_Table;
    
  2. (オプション)表の列に新しい名前を付けます。

    ALTER TABLE Contacts_Table
      RENAME COLUMN Name TO Name_1;
    
    ALTER TABLE Contacts_Table
      RENAME COLUMN Phone_Number TO Phone_Number_1;
    
  3. エディショニング・ビューを作成します。

    CREATE OR REPLACE EDITIONING VIEW Contacts AS
      SELECT
        ID                 ID,
        Name_1             Name,
        Phone_Number_1     Phone_Number
      FROM Contacts_Table;
    
  4. トリガーContacts_BIを表からエディショニング・ビューに移動します。

    DROP TRIGGER Contacts_BI;
     
    CREATE TRIGGER Contacts_BI
      BEFORE INSERT ON Contacts FOR EACH ROW
    BEGIN
      :NEW.ID := Contacts_Seq.NEXTVAL;
    END;
    /
サンプル・アプリケーションをアップグレードするためのEBRの使用

トリガーを使用して、既存のアプリケーションをアップグレードできます。

例: サンプル・アプリケーションをアップグレードするエディションの作成

例27-10では、既存のアプリケーション(「既存のアプリケーション」内)をアップグレードするエディションを作成し、新しいエディションをセッション・エディションにして、新しいエディションが実際にセッション・エディションであることをチェックする方法を示します。

例27-10 サンプル・アプリケーションをアップグレードするエディションの作成

  1. 新しいエディションを作成します。

    CREATE EDITION Post_Upgrade AS CHILD OF Ora$Base;
    
  2. 新しいエディションをセッション・エディションにします。

    ALTER SESSION SET EDITION = Post_Upgrade;
    
  3. セッション・エディションをチェックします。

    SELECT
    SYS_CONTEXT('Userenv', 'Current_Edition_Name') "Current_Edition"
    FROM DUAL;
    

    結果:

    Current_Edition
    -----------------------------------------------------------------------------
    POST_UPGRADE
     
    1 row selected.
    

「例: サンプル・アプリケーションをアップグレードするエディションの作成」は、Post_Upgradeエディションで、物理表に新しい列を追加し、列の追加により無効化されたトリガーを再コンパイルする方法を示します。エディショニング・ビューContactsが表の列を適切な論理名で選択するように、このエディショニング・ビューを置換する方法を示します。

注意:

実表を変更するため、非ブロック化およびブロック化のDDL文を参照してください。

例: 表の変更とエディショニング・ビューの置換

例27-11は、Post_Upgradeエディションで、forward crosseditionトリガーにより使用されるプロシージャを2つ作成し、無効な状態のforward crosseditionトリガーとreverse crosseditionトリガーの両方を作成してから、これらを有効化する方法を示します。

例27-11 表の変更とエディショニング・ビューの置換

  1. 物理表に新しい列を追加します。

    ALTER TABLE Contacts_Table ADD (
      First_Name_2     varchar2(20),
      Last_Name_2      varchar2(25),
      Country_Code_2   varchar2(20),
      Phone_Number_2   varchar2(20)
    );
    

    (これは非ブロック化DDLです。)

  2. 無効化されたトリガーを再コンパイルします。

    ALTER TRIGGER Contacts_BI COMPILE REUSE SETTINGS;
    
  3. エディショニング・ビューを置換して、このエディショニング・ビューが置換列を適切な論理名で選択するようにします。

    CREATE OR REPLACE EDITIONING VIEW Contacts AS
      SELECT
        ID                 ID,
        First_Name_2       First_Name,
        Last_Name_2        Last_Name,
        Country_Code_2     Country_Code,
        Phone_Number_2     Phone_Number
      FROM Contacts_Table;
    
例: crosseditionトリガーの作成と有効化

例27-12は、Post_Upgradeエディションで、トランスフォームを適用する方法を示します。

例27-12 crosseditionトリガーの作成と有効化

  1. forward crosseditionトリガーにより使用される1つ目のプロシージャを作成します。

    CREATE OR REPLACE PROCEDURE Set_First_And_Last_Name (
      Name        IN  VARCHAR2,
      First_Name  OUT VARCHAR2,
      Last_Name   OUT VARCHAR2)
    IS
      Comma_Pos NUMBER := INSTR(Name, ',');
    BEGIN
      IF Comma_Pos IS NULL OR Comma_Pos < 2 THEN
        RAISE Program_Error;
      END IF;
     
      Last_Name := SUBSTR(Name, 1, Comma_Pos-1);
      Last_Name := RTRIM(Ltrim(Last_Name));
     
      First_Name := SUBSTR(Name, Comma_Pos+1);
      First_Name := RTRIM(LTRIM(First_Name));
    END Set_First_And_Last_Name;
    /
    
  2. forward crosseditionトリガーにより使用される2つ目のプロシージャを作成します。

    CREATE OR REPLACE PROCEDURE Set_Country_Code_And_Phone_No (
      Phone_Number     IN  VARCHAR2,
      Country_Code     OUT VARCHAR2,
      Phone_Number_V2  OUT VARCHAR2)
    IS
      Char_To_Number_Error EXCEPTION;
      PRAGMA EXCEPTION_INIT(Char_To_Number_Error, -06502);
      Bad_Phone_Number EXCEPTION;
      Nmbr VARCHAR2(30) := REPLACE(Phone_Number, '.', '-');
     
      FUNCTION Is_US_Number(Nmbr IN VARCHAR2)
        RETURN BOOLEAN
      IS
        Len NUMBER := LENGTH(Nmbr);
        Dash_Pos NUMBER := INSTR(Nmbr, '-');
        n PLS_INTEGER;
      BEGIN
        IF Len IS NULL OR Len <> 12 THEN
          RETURN FALSE;
        END IF;
        IF Dash_Pos IS NULL OR Dash_Pos <> 4 THEN
          RETURN FALSE;
        END IF;
        BEGIN
          n := TO_NUMBER(SUBSTR(Nmbr, 1, 3));
        EXCEPTION WHEN Char_To_Number_Error THEN
          RETURN FALSE;
        END;
     
        Dash_Pos := INSTR(Nmbr, '-', 5);
     
        IF Dash_Pos IS NULL OR Dash_Pos <> 8 THEN
          RETURN FALSE;
        END IF;
     
        BEGIN
          n := TO_NUMBER(SUBSTR(Nmbr, 5, 3));
        EXCEPTION WHEN Char_To_Number_Error THEN
          RETURN FALSE;
        END;
     
        BEGIN
          n := TO_NUMBER(SUBSTR(Nmbr, 9));
        EXCEPTION WHEN Char_To_Number_Error THEN
          RETURN FALSE;
        END;
     
        RETURN TRUE;
      END Is_US_Number;
     
    BEGIN
      IF Nmbr LIKE '011-%' THEN
        DECLARE
          Dash_Pos NUMBER := INSTR(Nmbr, '-', 5);
        BEGIN
          Country_Code := '+'|| TO_NUMBER(SUBSTR(Nmbr, 5, Dash_Pos-5));
          Phone_Number_V2 := SUBSTR(Nmbr, Dash_Pos+1);
        EXCEPTION WHEN Char_To_Number_Error THEN
          raise Bad_Phone_Number;
        END;
      ELSIF Is_US_Number(Nmbr) THEN
        Country_Code := '+1';
        Phone_Number_V2 := Nmbr;
      ELSE
        RAISE Bad_Phone_Number;
      END IF;
    EXCEPTION WHEN Bad_Phone_Number THEN
      Country_Code := '+0';
      Phone_Number_V2 := '000-000-0000';
    END Set_Country_Code_And_Phone_No;
    /
    
  3. 無効な状態のforward crosseditionトリガーを作成します。

    CREATE OR REPLACE TRIGGER Contacts_Fwd_Xed
      BEFORE INSERT OR UPDATE ON Contacts_Table
      FOR EACH ROW
      FORWARD CROSSEDITION
      DISABLE
    BEGIN
      Set_First_And_Last_Name(
        :NEW.Name_1,
        :NEW.First_Name_2,
        :NEW.Last_Name_2
      );
      Set_Country_Code_And_Phone_No(
        :NEW.Phone_Number_1,
        :NEW.Country_Code_2,
        :NEW.Phone_Number_2
      );
    END Contacts_Fwd_Xed;
    /
    
  4. forward crosseditionトリガーを有効化します。

    ALTER TRIGGER Contacts_Fwd_Xed ENABLE;
    
  5. 無効な状態のreverse crosseditionトリガーを作成します。

    CREATE OR REPLACE TRIGGER Contacts_Rvrs_Xed
      BEFORE INSERT OR UPDATE ON Contacts_Table
      FOR EACH ROW
      REVERSE CROSSEDITION
      DISABLE
    BEGIN
      :NEW.Name_1 := :NEW.Last_Name_2||', '||:NEW.First_Name_2;
      :NEW.Phone_Number_1 :=
      CASE :New.Country_Code_2
        WHEN '+1' THEN
          REPLACE(:NEW.Phone_Number_2, '-', '.')
        ELSE
          '011.'||LTRIM(:NEW.Country_Code_2, '+')||'.'||
          REPLACE(:NEW.Phone_Number_2, '-', '.')
      END;
    END Contacts_Rvrs_Xed;
    /
    
  6. reverse crosseditionトリガーを有効化します。

    ALTER TRIGGER Contacts_Rvrs_Xed ENABLE;
    
  7. 保留中の変更がコミットまたはロールバックされるまで待機します。

    DECLARE
      scn              NUMBER  := NULL;
      timeout CONSTANT INTEGER := NULL;
    BEGIN
      IF NOT DBMS_UTILITY.WAIT_ON_PENDING_DML(Tables  => 'Contacts_Table',
                                              timeout => timeout,
                                              scn     => scn)
      THEN
        RAISE_APPLICATION_ERROR(-20000,
         'Wait_On_Pending_DML() timed out. CETs were enabled before SCN: '||SCN);
      END IF;
    END;
    /
    

関連項目:

DBMS_UTILITY.WAIT_ON_PENDING_DMLプロシージャの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。

例: トランスフォームの適用

Post_Upgradeエディションで、例27-13の例は、トランスフォームを適用する方法を示します。

例27-13 トランスフォームの適用

DECLARE
  c NUMBER := DBMS_SQL.OPEN_CURSOR();
  x NUMBER;
BEGIN
  DBMS_SQL.PARSE(
    c                          => c,
    Language_Flag              => DBMS_SQL.NATIVE,
    Statement                  => 'UPDATE Contacts_Table SET ID = ID',
    Apply_Crossedition_Trigger => 'Contacts_Fwd_Xed'
  );
  x := DBMS_SQL.EXECUTE(c);
  DBMS_SQL.CLOSE_CURSOR(c);
  COMMIT;
END;
/
 
例: 変更された表のデータ表示

例27-14は、Post_Upgradeエディションで、変更が意図したとおりに機能しているかどうかをチェックする方法を示します。「例: 変更された表のデータの表示」「例: 既存の表のデータの表示」と比較します。

例27-14 変更された表のデータ表示

  1. 列が読みやすくなるように書式設定します。

    COLUMN ID FORMAT 999
    COLUMN Last_Name FORMAT A15
    COLUMN First_Name FORMAT A15
    COLUMN Country_Code FORMAT A12
    COLUMN Phone_Number FORMAT A12
    
  2. 問合せ:

    SELECT * FROM Contacts
    ORDER BY Last_Name;
    

    結果:

      ID FIRST_NAME      LAST_NAME       COUNTRY_CODE PHONE_NUMBER
    ---- --------------- --------------- ------------ ------------
     174 Ellen           Abel            +44          1644-429267
     166 Sundar          Ande            +44          1346-629268
     130 Mozhe           Atkinson        +1           650-124-6234
     105 David           Austin          +1           590-423-4569
     204 Hermann         Baer            +1           515-123-8888
     116 Shelli          Baida           +1           515-127-4563
     167 Amit            Banda           +44          1346-729268
     172 Elizabeth       Bates           +44          1343-529268
     192 Sarah           Bell            +1           650-501-1876
     151 David           Bernstein       +44          1344-345268
     129 Laura           Bissot          +1           650-124-5234
     169 Harrison        Bloom           +44          1343-829268
     185 Alexis          Bull            +1           650-509-2876
     187 Anthony         Cabrio          +1           650-509-4876
     154 Nanette         Cambrault       +44          1344-987668
     148 Gerald          Cambrault       +44          1344-619268
     110 John            Chen            +1           515-124-4269
           ...
     120 Matthew         Weiss           +1           650-123-1234
     200 Jennifer        Whalen          +1           515-123-4444
     149 Eleni           Zlotkey         +44          1344-429018
     
    107 rows selected.
    

変更が意図どおりに機能した場合は、「crosseditionトリガーを使用するEBRの手順」のステップ10から13を実行することができます。