エディションベースの再定義(EBR)を使用すると、アプリケーションの使用中にそのデータベース・コンポーネントをアップグレードでき、停止時間を最小化あるいは排除することができます。
使用中にアプリケーションをアップグレードするには、アプリケーションを構成するデータベース・オブジェクトをコピーし、コピーしたオブジェクトを分離した状態で再定義します。変更内容はアプリケーションのユーザーには影響しません。ユーザーは変更されていないアプリケーションの実行を継続します。変更内容が正しいことを確認したら、アップグレードしたアプリケーションをすべてのユーザーが使用できるようにします。
EBRでは、1つ以上のコンポーネント機能を使用します。使用する機能と停止時間は次の要素によって異なります。
再定義するデータベース・オブジェクトの種類
データベース・オブジェクトの再定義中に、ユーザーがそのデータベース・オブジェクトをどの程度使用できるか
以前のアプリケーションを使用しているユーザーがいるときに、アップグレードしたアプリケーションを他のユーザーが使用できるようにするかどうか
データベース・オブジェクトをコピーし、コピーしたデータベース・オブジェクトを分離した状態で再定義するには、常にエディション機能を使用します。この章で説明するオンラインでのアプリケーション・アップグレード手順がエディションベースの再定義(EBR)と呼ばれるのはこのためです。
再定義するすべてのオブジェクトがエディション化(定義は24.1.1項を参照)されている場合、使用する機能はエディションのみです。
表はエディション・オブジェクトではありません。1つ以上の表の構造を変更する場合は、エディショニング・ビュー機能も使用します。
表の構造を変更している間、他のユーザーがその表のデータを変更する必要がある場合は、forward crosseditionトリガーも使用します。アップグレード前のアプリケーションとアップグレード後のアプリケーションが同時に通常使用(ホット・ロールオーバー)されている場合、reverse crosseditionトリガーも使用します。crosseditionトリガーはアプリケーションの永続的な要素ではありません。全ユーザーがアップグレード後のアプリケーションを使用するようになったら削除します。
あるアプリケーションが他のエディションでも実行される場合に、1つのエディションでそのアプリケーションに対して実行可能なEBR操作は、ライブ操作です。
内容は次のとおりです。
エディションはスキーマ・オブジェクトではなく、所有者もありません。エディションは1つのネームスペースに作成されます。複数のエディションがデータベースに共存することができます。
データベースには少なくとも1つのエディションが必要です。新規作成またはアップグレードされたOracle Databaseはすべて、ora$base
という名前の1つのエディションから開始されます。
内容は次のとおりです。
注意: ユーザーとスキーマという用語は同義です。スキーマ・オブジェクトの所有者は、これを所有するユーザー/スキーマです。 |
エディション・オブジェクトには、所有者でエディション対応のスキーマ・オブジェクト・タイプとEDITIONABLE
プロパティの両方があります。エディションにはエディション・オブジェクトの独自のコピーがあり、そのエディションに対してはこのコピーのみが表示可能です。
非エディション・オブジェクトには、所有者で非エディション対応のスキーマ・オブジェクト・タイプまたはNONEDITIONABLE
プロパティのいずれかがあります。エディションは、非エディション・オブジェクトの独自のコピーを持つことはできません。非エディション・オブジェクトは、すべてのエディションに対して表示可能です。
オブジェクトは、所有者におけるタイプに対するエディションの有効化によってエディション・オプションになる場合(詳細は、24.1.1.4項「ユーザーに対するエディションの有効化」を参照)、潜在的にエディション対応になります。
エディション・オブジェクトは、スキーマとエディションの両方に属し、そのOBJECT_NAME
、OWNER
、およびEDITION_NAME
により一意に識別されます。非エディション・オブジェクトは、スキーマのみに属し、そのOBJECT_NAME
およびOWNER
により(EDITION_NAME
はNULL
)一意に識別されます。(厳密に言えば、オブジェクトを一意に識別するにはオブジェクトのNAMESPACE
も必要ですが、オブジェクトを参照する文では暗黙的または明示的にNAMESPACE
が指定されるので、これは無視しても構いません)。
オブジェクトのOBJECT_NAME
、OWNER
、およびEDITION_NAME
は、静的データ・ディクショナリ・ビュー*_OBJECTS
および*_OBJECTS_AE
に表示できます。
オブジェクトのEDITION_NAME
を知らなくても、このオブジェクトを参照できます(知っていても、指定できません)。参照のコンテキストで、エディションを暗黙的に指定します。コンテキストがデータ定義言語(DDL)文である場合、エディションは、このコマンドを発行したセッションの現行エディションです(現行エディションの詳細は、24.1.6項を参照)。コンテキストがソース・コードである場合、エディションはオブジェクトが実オブジェクトであるものです(24.1.3項を参照)。
内容は次のとおりです。
オブジェクト名の解決を試行するために、Oracle Databaseは、23.7項で説明されている手順を使用します。プロシージャを正常に実行するには、オブジェクト名のすべての部分が現行エディションで表示されている必要があります。
エディション・オブジェクトの名前解決時には、現行エディションのエディション・オブジェクトと非エディション・オブジェクトの両方が表示可能です。
非エディション・オブジェクトの名前解決時には、非エディション・オブジェクトのみが表示可能です。したがって、エディション・オブジェクトを参照する非エディション・オブジェクトを作成しようとすると(24.1.1.2項で説明されている場合を除く)、作成は失敗し、エラーが表示されます。
参照対象のエディション・オブジェクトを変更する場合、そのすべての依存(直接および間接)が無効になります。無効なオブジェクトが参照されると、データベースはそのオブジェクトを検証しようとします。
通常、非エディション・オブジェクトはエディション・オブジェクトに依存できません。これは、名前解決時にはエディション・オブジェクトは表示できないためです。ただし、非エディション・オブジェクトは、名前解決時にエディション・オブジェクトを検索するためにエディション(評価エディション)を指定すると、エディション・オブジェクトに依存できます。評価エディションを指定するには、非エディション・オブジェクトは次のいずれかである必要があります。
マテリアライズド・ビュー
仮想列
内容は次のとおりです。
マテリアライズド・ビューは、評価エディションを指定することによってエディション・オブジェクトに依存できるようにする非エディション・オブジェクトです。エディション・オブジェクトに依存するマテリアライズド・ビューは、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
を省略すると、名前解決時にエディション・オブジェクトは表示できなくなります。
CREATE
MATERIALIZED
VIEW
文の完全な構文およびセマンティクスについては、『Oracle Database SQL言語リファレンス』を参照してください。
評価エディションまたは使用不可エディションを無効化、有効化または変更するには、ALTER
MATERIALIZED
VIEW
文を使用します。詳細は、『Oracle Database SQL言語リファレンス』を参照してください。
マテリアライズド・ビューの評価エディションおよび使用不可エディションを表示するには、静的データ・ディクショナリ・ビュー*_MVIEWS
(詳細は、『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
の詳細は、24.1.1.2.1項を参照してください。
仮想列が起動するファンクションの依存性は保持されません。したがって、評価エディションが削除されるか、仮想列が非エディション・ファンクションに依存しているときに、ファンクションがエディション化されると、次のいずれかの例外が発生する可能性があります。
仮想列の問合せ試行
仮想列が含まれる行の更新試行
仮想列へのアクセスを試行するトリガー
仮想列定義の完全な構文およびセマンティクスについては、『Oracle Database SQL言語リファレンス』を参照してください。
仮想列の評価エディションを表示するには、静的データ・ディクショナリ・ビュー*_TAB_COLS
(『Oracle Databaseリファレンス』を参照)を使用します。
スキーマ内のスキーマ・オブジェクト・タイプをエディション対応にするには、データベース内でエディション対応にする必要があります。データベース内でエディション対応のスキーマ・オブジェクト・タイプは、COMPATIBLE
初期化パラメータ(『Oracle Database管理者ガイド』を参照)の値によって決定され、動的パフォーマンス・ビューV$EDITIONABLE_TYPES
(『Oracle Databaseリファレンス』を参照)によって表示されます。
COMPATIBLE
の値が12以上である場合、データベース内で次のスキーマ・オブジェクト・タイプがエディション対応になります。
SYNONYM
VIEW
SQL翻訳プロファイル
すべてのPL/SQLオブジェクト型:
FUNCTION
LIBRARY
PACKAGE
およびPACKAGE
BODY
PROCEDURE
TRIGGER
TYPE
およびTYPE
BODY
他のすべてのスキーマ・オブジェクト・タイプはデータベースおよびすべてのスキーマ内で非エディション対応であり、そのタイプのオブジェクトは常にエディション化されません。非エディション対応スキーマ・オブジェクト・タイプの例はTABLE
です。表は常に非エディション化オブジェクトです。
スキーマ・オブジェクト・タイプがデータベース内でエディション対応である場合、スキーマ内でエディション対応にできます。詳細は、24.1.1.4項を参照してください。
注意:
|
ユーザーに対してエディションを有効化するには、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リファレンス』を参照)によってこのスキーマに対して表示されるタイプです。
参照: CREATE USER およびALTER USER の各文の完全な構文とセマンティクスの詳細は、『Oracle Database SQL言語リファレンス』を参照してください |
エディションの有効化は遡及的で、これを元に戻すことはできません。ユーザーに対してエディションを有効化すると、このユーザーは永続的にエディション対応になります。スキーマ内のスキーマ・オブジェクト・タイプに対してエディションを有効化すると、このタイプはそのスキーマ内で永続的にエディション対応になります。エディション対応のユーザーが所有するか所有予定のオブジェクトはすべて、そのタイプがスキーマ内でエディション対応であるとともにEDITIONABLE
プロパティを持つ場合、エディション・オブジェクトになります。EDITIONABLE
プロパティの詳細は、24.1.1.5項を参照してください。
内容は次のとおりです。
潜在的なエディション・オブジェクトにエディション化されていない依存がある場合、潜在的なエディション・オブジェクトの所有者に対してエディションを有効化できるのは、次のいずれかが該当する場合のみです。
潜在的なエディション・オブジェクトの所有者に対してエディションを有効化すると、エディション化されていない依存がエディション化される場合。
ALTER USER user ENABLE EDITIONS [ FOR type [, type ]... ] FORCE;
前述の文では、指定されたユーザーについてエディションは有効化され、エディション・オブジェクトに対する非エディション依存オブジェクトは無効化されます。依存オブジェクトの無効化の詳細は、23.4項を参照してください。
FORCE
は、次の状況で便利です。ユーザーA
とB
に対してエディションを有効化する必要がある場合。ユーザーA
が潜在的エディション・オブジェクトa1
とa2
の所有者である場合。ユーザーB
が潜在的エディション・オブジェクトb1
とb2
の所有者である場合。オブジェクトa1
がオブジェクトb1
に依存している場合。オブジェクトb2
がオブジェクトa2
に依存している場合。ユーザーA
とB
に対してエディションを有効化させるには、次のようにします。
FORCE
を使用して、ユーザーA
についてエディションを有効化します。
ALTER USER A ENABLE EDITIONS FORCE;
これで、a1
とa2
はエディション・オブジェクトになり、非エディション・オブジェクトb2
(a2
に依存するもの)は無効になりました。
ユーザーB
のエディションを有効化します。
ALTER USER B ENABLE EDITIONS;
これで、b1
とb2
はエディション・オブジェクトになります。ただし、b2
は無効のままです。
COMPILE
で、適切なALTER
文を使用して、b2
を再コンパイルします。PL/SQLオブジェクトについては、REUSE
SETTINGS
も指定してください。
たとえば、b2
がプロシージャの場合、次の文を使用します。
ALTER PROCEDURE b2 COMPILE REUSE SETTINGS
PL/SQLオブジェクトのためのALTER
文の詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。
SQLオブジェクトのためのALTER
文の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。
FORCE
は、次の状況では必要ありません。潜在的エディション・オブジェクトc1
を所有しているユーザーC
に対してエディションを有効化する必要がある場合。オブジェクトc1
が、ユーザーD
により所有されていて、潜在的エディション依存オブジェクトd1
を持っている場合。ユーザーD
が、所有者がC
である依存オブジェクトを持つ、潜在的エディション・オブジェクトを所有していない場合。最初にd1
をエディション・オブジェクトにして、D
に対してエディションを有効化した場合、非エディション・オブジェクトはエディション・オブジェクトに依存できないという規則に違反せずに、C
に対してエディションを有効化することができます。
次のユーザーに対してはエディションを有効化できません。
Oracleが提供するユーザー
CDBの共通ユーザー
CDB内の共通ユーザーの詳細は、『Oracle Database管理者ガイド』を参照してください。
有効化しようとすると、エラーORA-38820が発生します。ADTが表への依存性を持っていない場合、ALTER
TYPE
RESET
文を使用して、バージョンを1にリセットすることにより、それ以上、表が進化するとみなされないようにすることができます(ADTのバージョンを1にリセットすると、これに依存するものは無効化されます。)ALTER
TYPE
RESET
文の構文については、『Oracle Database PL/SQL言語リファレンス』を参照してください。
注意: データベースをリリース11.2からリリース12.1にアップグレードすると、ユーザーが作成したスキーマ内のオブジェクトがEDITIONABLE プロパティを取得し、パブリック・シノニムがNONEDITIONABLE プロパティを取得します。 |
データベース内でエディション対応であるスキーマ・オブジェクト・タイプに対してCREATE
およびALTER
文を使用すると、作成または変更するオブジェクトをEDITIONABLE
またはNONEDITIONABLE
として指定できます。
DBMS_SQL_TRANSLATOR.CREATE_PROFILE
プロシージャを使用すると、作成するSQL翻訳プロファイルをEDITIONABLE
またはNONEDITIONABLE
として指定できます。
EDITIONABLE
であるオブジェクトを確認するには、静的データ・ディクショナリ・ビュー*_OBJECTS
(『Oracle Databaseリファレンス』を参照)または*_OBJECTS_AE
(『Oracle Databaseリファレンス』を参照)のEDITIONABLE
列を確認してください。
内容は次のとおりです。
参照:
|
データベース内でタイプがエディション対応である新規スキーマ・オブジェクトを作成する場合、EDITIONABLE
またはNONEDITIONABLE
プロパティを指定できます。このプロパティを省略する場合、オブジェクトは次のいずれかでないかぎり、デフォルトではEDITIONABLE
になります。
PUBLIC
SYNONYM
(デフォルトではNONEDITIONABLE
です)
PACKAGE
BODY
(パッケージ仕様のプロパティを継承します)
TYPE
BODY
(タイプ仕様のプロパティを継承します)
PACKAGE
BODY
またはTYPE
BODY
では、プロパティを指定する場合、対応するパッケージまたはタイプ仕様のプロパティと一致する必要があります。
それ自体のスキーマ内でエディション対応であるタイプのEDITIONABLE
オブジェクトを作成する場合、新規オブジェクトは、オブジェクトの作成時に現行エディションであるエディションでのみ表示可能なエディション・オブジェクトです。(現行エディションの詳細は、24.1.6項を参照)。エディション・オブジェクトの作成は、新規オブジェクトを表示できないエディションに関してのライブ操作です。
NONEDITIONABLE
プロパティを持つオブジェクト、またはそれ自体のスキーマ内で非エディション対応であるタイプのオブジェクトを作成する場合、新規オブジェクトは、すべてのエディションで表示可能な非エディション・オブジェクトです。
現行エディションでは、obj
という名前のスキーマ・オブジェクトがスキーマ内にあるが、別のエディションでは、obj
という名前のエディション・オブジェクトがスキーマ内にあるとします。現行エディションのスキーマでは、obj
という名前のオブジェクトを作成できますが、これはエディション・オブジェクトである(つまり、OBJECT_NAME
、OWNER
およびEDITION_NAME
により一意に識別される)必要があります。新規オブジェクトのタイプ(同じ名前を持つ既存のエディション・オブジェクトのタイプとは異なる場合があります)はスキーマ内でエディション対応である必要があり、新規オブジェクトはEDITIONABLE
プロパティを持つ必要があります。例24-2および例24-3を参照してください。
既存のオブジェクトを(CREATE
OR
REPLACE
またはALTER
文を使用して)置換または変更する場合、次のようになります。
スキーマがエディションに対して有効化されていない場合、オブジェクトのプロパティをEDITIONABLE
からNONEDITIONABLE
(またはこの逆)に変更できます。
置換または変更対象のオブジェクトのタイプについてスキーマがエディションに対して有効化されている場合、オブジェクトのプロパティをEDITIONABLE
からNONEDITIONABLE
(またはこの逆)に変更できません。
エディション・オブジェクトの変更は、変更されたオブジェクトを表示できないエディションに関してのライブ操作です。
通常、非エディション・オブジェクトはエディション・オブジェクトに依存できません(詳細は、24.1.1.1項を参照)。
抽象データ型(ADT)をエディション化し、同時に進化させることはできません。
型進化の詳細は、『Oracle Databaseオブジェクト・リレーショナル開発者ガイド』を参照してください。
エディション・オブジェクトを、FOREIGN
KEY
制約の始点、または終点にすることはできません。
この規則は、エディション・ビューに対してのみ影響します。エディション化されたビューとは、通常のビュー、またはエディショニング・ビューのどちらかです。
注意: CDBのルートではエディションを作成しないことをお薦めします。CDBの詳細は、『Oracle Database管理者ガイド』を参照してください。 |
エディションを作成するには、SQL文CREATE
EDITION
を使用します。
エディションは既存のエディションの子として作成する必要があります。CREATE
EDITION
文によって作成される最初のエディションの親はora$base
です。次の文によって、ora$base
の子としてエディションe2
が作成されます。
CREATE EDITION e2
(例24-1などでこの文が使用されています。)
エディションの子は最大で1つです。
エディションの子孫は、エディションの子、子の子、その子などを指します。エディションの祖先は、エディションの親、親の親、その親などを指します。ルート・エディションには親はありません。また、リーフ・エディションには子はありません。
参照: 使用するための権限も含む、CREATE EDITION 文の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。 |
エディションを作成すると、親エディションのエディション・オブジェクトがすべてこのエディションにコピーされます。1つのエディション内のエディション・オブジェクトを変更しても、他のエディション内のこのエディション・オブジェクトのコピーには影響しません。
前述のパラグラフでは、どのような処理が行われるかを概念的に説明しています。実際には、パフォーマンスを最適化するために、Oracle Databaseがエディション・オブジェクトを祖先エディションから子孫エディションにコピーするのは、子孫エディションがオブジェクトを変更する場合のみです。この方法は変更時のコピーと呼ばれます。
子孫エディションに(実際にではなく)概念的にコピーされたエディション・オブジェクトは、継承オブジェクトと呼ばれます。子孫エディションのユーザーがDDL文で継承オブジェクトを参照すると、Oracle Databaseはオブジェクトを子孫エディションに実際にコピーします。このコピー操作は実現化と呼ばれ、子孫エディションで実オブジェクトが作成されます。
例24-1では、エディションora$base
でプロシージャhello
を作成してから、ora$base
の子としてエディションe2
を作成します。e2
がhello
を起動するときは、ora$base
で継承プロシージャを起動します。このとき、e2
はhello
を変更して、実オブジェクト化します。ここで、e2
がhello
を起動するときは、独自の実プロシージャを起動します。エディションora$base
内のプロシージャhello
は変更されずに残ります。
例24-1 エディション・オブジェクトおよび変更時のコピー
次のプロシージャがora$base
でエディション・オブジェクトであると仮定します。
CREATE OR REPLACE PROCEDURE hello IS BEGIN DBMS_OUTPUT.PUT_LINE('Hello, edition 1.'); END hello; /
ora$base
で、プロシージャを起動します。
BEGIN hello(); END; /
結果:
Hello, edition 1.
PL/SQL procedure successfully completed.
子エディションを作成します。
CREATE EDITION e2;
概念的に、プロシージャが子エディションにコピーされ、子エディションではこのコピーのみが表示可能です。このコピーは継承オブジェクトであり、実オブジェクトではありません。
子エディションを使用します。
ALTER SESSION SET EDITION = e2;
ALTER
SESSION
SET
EDITION
の詳細は、24.1.6.2項を参照してください。
プロシージャを起動します。
BEGIN hello(); END; /
概念的に、子エディションはプロシージャ(これは親エディションora$base
内のプロシージャと同等です)の独自のコピーを起動します。ただし、子エディションは実際には親エディション内のプロシージャを起動します。結果:
Hello, edition 1.
PL/SQL procedure successfully completed.
プロシージャを変更します。
CREATE OR REPLACE PROCEDURE hello IS
BEGIN
DBMS_OUTPUT.PUT_LINE('Hello, edition 2.');
END hello;
/
Oracle Databaseは子エディション内のプロシージャを実現化し、変更は、親エディション内のプロシージャではなく、子エディション内の実オブジェクトにのみ影響します。
プロシージャを起動します。
BEGIN hello(); END; /
子エディションは独自の実プロシージャを起動します。
Hello, edition 2.
PL/SQL procedure successfully completed.
親エディションに戻ります。
ALTER SESSION SET EDITION = ora$base;
プロシージャを起動し、これが変更されていないことを確認します。
BEGIN hello(); END; /
結果:
Hello, edition 1.
PL/SQL procedure successfully completed.
例24-2は、エディションora$base
でプロシージャgoodbye
を作成してから、ora$base
の子としてエディションe2
を作成します。e2
でgoodbye
が削除されると、e2はgoodbyeを起動できなくなりますが、ora$base
では起動できます(使用するための権限も含む、DROP
PROCEDURE
文の詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください)。
例24-2 エディション・オブジェクトの削除
次のプロシージャがora$base
でエディション・オブジェクトであると仮定します。
CREATE OR REPLACE PROCEDURE goodbye IS BEGIN DBMS_OUTPUT.PUT_LINE('Good-bye!'); END goodbye; /
プロシージャを起動します。
BEGIN goodbye; END; /
結果:
Good-bye! PL/SQL procedure successfully completed.
ora$base
の子としてエディションe2
を作成します。
CREATE EDITION e2;
e2
では、プロシージャは継承オブジェクトです。
エディションe2
を使用します。
ALTER SESSION SET EDITION = e2;
ALTER
SESSION
SET
EDITION
はトップレベルのSQL文である必要があります。詳細は、第24.1.6.2項を参照してください。
e2
で、プロシージャを起動します。
BEGIN goodbye; END; /
e2
がora$base
でプロシージャを起動します。
Good-bye! PL/SQL procedure successfully completed.
e2
で、プロシージャを削除します。
DROP PROCEDURE goodbye;
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
ora$base
に戻ります。
ALTER SESSION SET EDITION = ora$base;
ora$base
で、プロシージャを起動します。
BEGIN goodbye; END; /
結果:
Good-bye! PL/SQL procedure successfully completed.
e2
でプロシージャgoodbye
が削除されたため、次のようになります。
子孫では、プロシージャgoodbye
が継承されません。
goodbye
というオブジェクトはe2
で表示可能でないため、e2
では、goodbye
という名前を付けてオブジェクトを作成できますが、これはエディション・オブジェクトである必要があります(詳細は、24.1.1.5.1項を参照)。goodbye
という名前の新規エディション・オブジェクトをe2
が作成すると、e2
の子孫がこのオブジェクトを継承します。
例24-3では、e2
にgoodbye
という名前のファンクションが作成され、その後、e2
の子としてe3
という名前のエディションが作成されます。e3
でプロシージャgoodbye
(e2
で削除)を起動しようとすると、エラーが発生しますが、e3
でファンクションgoodbye
(e2
で作成)は正常に起動されます。
例24-3 削除済継承オブジェクトの名前を使用したオブジェクトの作成
e2
に戻ります。
ALTER SESSION SET EDITION = e2;
ALTER
SESSION
SET
EDITION
の詳細は、24.1.6.2項を参照してください。
e2
で、goodbye
という名前のファンクションを作成します。
CREATE OR REPLACE FUNCTION goodbye RETURN BOOLEAN IS BEGIN RETURN(TRUE); END goodbye; /
このファンクションはエディション・オブジェクトである必要があります。デフォルトでは、これはEDITIONABLE
プロパティを持ちます。タイプFUNCTION
がスキーマ内でエディション対応ではない場合、ALTER
USER
文を使用してエディション対応にする必要があります(詳細は、24.1.1.4項を参照)。
エディションe3
を作成します。
CREATE EDITION e3 AS CHILD OF e2;
エディションe3
がファンクションgoodbye
を継承します。
エディションe3
を使用します。
ALTER SESSION SET EDITION = e3;
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
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
GRANT
文の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。
このエディションを、データベースのデフォルト・エディションにします。
ALTER DATABASE DEFAULT EDITION = edition_name
これには、edition_name
のUSE
権限がPUBLIC
に効率的に付与されるため、すべてのユーザーがエディションを使用できるという副作用があります。
ALTER
DATABASE
文の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。
各データベース・セッションで一度に使用されるエディションは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
権限のある任意のエディションに変更できます。セッション・エディションを変更すると、現行エディションも同じエディションに変更されます。
例24-1および例24-2に含まれる次の文は、まずセッション・エディション(現行エディション)を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トリガーが起動される場合。
詳細は、24.3.3項「crosseditionトリガーとエディションの相互作用」を参照してください。
例24-4のように、DBMS_SQL
.PARSE
プロシージャをコールして、文を実行するエディションを指定することで、文を実行する場合。
文が実行している間、指定されたエディションが現行エディションになりますが、セッション・エディションは変更されません。DBMS_SQL
.PARSE
プロシージャの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。
例24-4では、セッション・エディションと現行エディションの名前を返すファンクションが作成されます。その後、子エディションが作成され、子エディションによってそのファンクションが2回起動されます。1回目はセッション・エディションと現行エディションは同じです。2回目は異なります。別のエディションがパラメータとしてDBMS_SQL
.PARSE
プロシージャに渡されるためです。
例24-4 セッション・エディションと異なる現行エディション
セッション・エディションと現行エディションの名前を返すファンクションを作成します。
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; /
子エディションを作成します。
CREATE EDITION e2 AS CHILD OF ora$base;
子エディションを使用します。
ALTER SESSION SET EDITION = e2;
ファンクションを起動します。
BEGIN DBMS_OUTPUT.PUT_LINE (session_and_current_editions()); END; /
結果:
Session: E2 / Current: E2
PL/SQL procedure successfully completed.
ファンクションをもう一度起動します。
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 /
REVOKE
文の詳細は『Oracle Database SQL言語リファレンス』を参照してください。
エディションをリタイアさせる場合、それに応じて非エディション・オブジェクトの評価エディションおよび未使用エディションを更新します。評価エディションおよび未使用エディションの変更の詳細は、24.1.1.2項「エディション・オブジェクトに依存可能な非エディション・オブジェクト」を参照してください。
エディションを削除するには、DROP
EDITION
文を使用します。詳細は、『Oracle Database SQL言語リファレンス』を参照してください。エディションに実オブジェクトがある場合は、実オブジェクトを削除するCASCADE
句を指定する必要があります。
DROP
EDITION
edition
CASCADE
文が正常終了前に(たとえば、停電などの理由で)中断された場合、静的データ・ディクショナリ・ビュー*_EDITIONS
には、edition
に対するUSABLE
の値がNO
であることが表示されます。このように使用できないedition
に対して実行できる唯一の操作は、DROP
EDITION
CASCADE
です。
エディションは次の場合に削除します。
アプリケーション・アップグレードをロールバックする必要がある場合。
(オプション)エディションをリタイアさせた場合。
エディションを削除できるのは、次のすべての条件に該当する場合のみです。
エディションがルート・エディション、またはリーフ・エディションである場合。
エディションがルートの場合、その子孫により継承されているオブジェクトを持っていない場合。(つまり、ルート・エディションから継承された各オブジェクトは、実オブジェクト化されたか、削除された場合)。
エディションが使用されていない場合(つまり、セッションの現行エディションまたはセッション・エディションではない場合)。
このエディションが、データベースのデフォルト・エディションではない場合。
子エディションで継承オブジェクトを明示的に実オブジェクト化するには、次のようにします。
子エディションをセッション・エディションにします。
詳細は、24.1.6.2項を参照してください。
COMPILE
で、適切なALTER
文を使用して、このオブジェクトを再コンパイルします。PL/SQLオブジェクトについては、REUSE
SETTINGS
も指定してください。
たとえば、次の文ではプロシージャp1
が実オブジェクト化されます。
ALTER PROCEDURE p1 COMPILE REUSE SETTINGS
PL/SQLオブジェクトのためのALTER
文の詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。
SQLオブジェクトのためのALTER
文の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。
エディションを削除する場合、それに応じて非エディション・オブジェクトの評価エディションおよび未使用エディションを更新します。評価エディションおよび未使用エディションの変更の詳細は、24.1.1.2項「エディション・オブジェクトに依存可能な非エディション・オブジェクト」を参照してください。
参照:
|
エディショニング・ビュー以外のビューで定義できるトリガーのタイプは、INSTEAD
OF
トリガーのみです。エディショニング・ビューでは、表で定義できるトリガー・タイプすべてを定義できます(ただし、crosseditionトリガー(一時トリガー)とINSTEAD
OF
トリガーは例外です)。このため、またエディショニング・ビューはエディション化が可能であることによって、エディショニング・ビューを使用することで、実表がエディション化されたかのように扱うことができます。ただし、アップグレードされたアプリケーションにより、新しい索引または制約が必要とされる場合、エディショニング・ビューに索引または制約を追加することはできません。これらは実表に追加する必要があります。
エディショニング・ビューは1つの実表の列のサブセットを選択し、オプションとしてそれらの列に別名を提供します。別名を提供するとき、エディショニング・ビューは物理列名(実表で使用される)を論理列名(アプリケーションで使用される)にマップします。エディショニング・ビューは、表のAPIに似ています。
直接ではなく、エディショニング・ビュー経由で表にアクセスすることに対するパフォーマンス・ペナルティはありません。つまり、SQL SELECT
、INSERT
、UPDATE
、DELETE
、またはMERGE
文で1つ以上のエディショニング・ビューが1回以上使用されているときに、必要に応じて、エディショニング・ビューの名前を実表の名前で置き換え、列名を調整した場合でも、パフォーマンスは変わりません。
静的データ・ディクショナリ・ビュー*_EDITIONING_VIEWS
は、セッション・エディションで表示可能なデータベース内のすべてのエディショニング・ビューを示します。*_EDITIONING_VIEWS_AE
は、すべてのエディションにおけるデータベース内のすべてのエディショニング・ビューのすべての実オブジェクトを示します。
内容は次のとおりです。
参照: 静的データ・ディクショナリ・ビュー*_EDITIONING_VIEWS および*_EDITIONING_VIEWS_AE の詳細は、『Oracle Databaseリファレンス』を参照してください。 |
エディショニング・ビューを作成する前に、所有者がエディション対応であり、スキーマ・オブジェクト・タイプVIEW
が所有者でエディション対応である必要があります。(詳細は、24.1.1.4項を参照。)
エディショニング・ビューを作成するには、SQL文CREATE
VIEW
をキーワードEDITIONING
とともに使用します。エディショニング・ビューを読取り専用にするには、WITH
READ
ONLY
を指定します。読取り/書込みにするにはWITH
READ
ONLY
を省略します。NONEDITIONABLE
は指定しないでください。指定すると、エラーが発生します。
エディショニング・ビューが読取り専用の場合、未変更アプリケーションのユーザーが実表のデータを見ることはできますが、変更することはできません。この実表は準可用性を備えています。準可用性を利用できるのは、ユーザーが読むだけで変更しない、オンライン・ディクショナリなどのアプリケーションです。実表にcrosseditionトリガーを定義しない場合は、エディショニング・ビューを読取り専用にします。
エディショニング・ビューが読取り/書込みの場合、未変更アプリケーションのユーザーが、実表のデータを見ることも変更することもできます。この実表は最大可用性を備えています。最大可用性が必要となるのは、ユーザーが注文を発行するオンライン・ストアなどのアプリケーションです。実表にcrosseditionトリガーを定義する場合は、エディショニング・ビューを読取り/書込みにします。
エディショニング・ビューは、実表からの列のサブセットの選択と列の別名提供の他にも機能を実行する必要があるため、エディショニング・ビューを作成するCREATE
VIEW
文には制限があります。制限に違反すると、FORCE
を指定していてもビューの作成が失敗します。
参照: 制限を含む、CREATE VIEW 文を使用したエディショニング・ビューの作成の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。 |
パーティション表に定義されているエディショニング・ビューには、パーティション拡張名を付けることができます。この名前は、実表のパーティションおよびサブパーティションを示すパーティション名とサブパーティション名を含みます。
パーティション拡張表名に対応するデータ操作言語(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
VIEW
をOR
REPLACE
句およびキーワードEDITIONING
とともに使用します。
エディショニング・ビューを置換できるのは別のエディショニング・ビューのみです。置換対象のエディショニング・ビューに定義されているトリガーはすべて保持されます。
エディショニング・ビューの定義が基づいている実表を削除したり名前を変更したりしても、エディショニング・ビューは削除されませんが、エディショニング・ビューとその依存オブジェクトが無効になります。ただし、エディショニング・ビューに定義されているトリガーはすべて保持されます。
アップグレードされたアプリケーションにより、新しい索引または制約が必要とされる場合は、これらを実表に追加する必要があります。これらをエディショニング・ビューに追加することはできません。
新しい索引が古いエディション(元のアプリケーション)に悪い影響を与える場合は、これらを非表示にします。新しい索引の使用が必要なcrosseditionトリガーで、これらをINDEX
ヒントに指定します。
すべてのユーザーがアップグレードされたアプリケーションのみを使用している場合は、次のようにします。
新しい索引を使用しているのがcrosseditionトリガーのみである場合は、これらの索引を削除します。
アップグレードされたアプリケーションが新しい索引で便利である場合は、これらを表示します。
参照:
|
crosseditionトリガーと非crosseditionトリガーの最も大きな違いは、エディションとの相互作用の方法です。crosseditionトリガーは、それが実であるエディションにのみ表示されます。子孫エディションでは表示されません。forward crosseditionトリガーは、データを古いエディションが使用していた列から、新しいエディションが使用している列に移動します。reverse crosseditionトリガーは逆方向へデータを移動します。
この他の重要な違いは次のとおりです。
crosseditionトリガーは、他の表に定義されたトリガーに対して並べ替えることができますが、非crosseditionトリガーは同じ表に定義されたトリガーに対してのみ並べ替えることができます。
crosseditionトリガーは一時的に使用します。構成を変更した表をすべてのユーザーが使用できるようにした後で削除します。
内容は次のとおりです。
参照: トリガーの詳細は、Oracle Database PL/SQL言語リファレンスを参照 |
アップグレード後のエディションでDML変更を表に行うと、新しい列または新しい表のみに書き込まれ、アップグレード前(祖先)エディションのユーザーが読取りまたは書込みを行う可能性がある列に対しては行われません。ただし、祖先エディションのユーザーが表データを変更する場合、表示しているエディショニング・ビューがそれらの変更内容を正確に反映する必要があります。これは、forward crosseditionトリガーを使用することで実現します。
forward crosseditionトリガーはトランスフォームを定義します。これは、古い行を1つ以上の新しい行に変換するための規則です。古い行は、アップグレード前の表現に含まれるデータ行です。新しい行は、アップグレード後の表現に含まれるデータ行です。トリガーの名前はトリガー自体、およびこのトリガーにより定義された変換を表します。
アップグレード前のエディションとアップグレード後のエディションが同時に通常使用(ホット・ロールオーバー)されている場合、reverse crosseditionトリガーを使用して、アップグレード後エディションのユーザーが表データを変更するときに、変更内容がアップグレード前エディションに正確に反映されるようにします。
crosseditionトリガーと非crosseditionトリガーの最も大きな違いは、エディションとの相互作用の方法です。
ここでは、現行エディションは、トリガーを起動するDML文が実行されるエディションを指します。現行エディションはセッション・エディションと異なることがあります(詳細は、24.1.6.4項を参照)。
内容は次のとおりです。
エディションは、非crosseditionトリガーを他のエディション・オブジェクトと同じように継承します(24.1.3項「エディション・オブジェクトおよび変更時のコピー」を参照)。
エディションはcrosseditionトリガーは継承しません。crosseditionトリガーは、別のエディションで実行されるDML文に対応して起動されることもありますが、名前が表示されるのは作成されたエディションのみです。したがって、エディションでは、祖先エディションで作成されたcrosseditionトリガーの名前を再利用できます。crosseditionトリガーの名前を再利用しても、古いトリガーの起動条件は変更されません。
静的データ・ディクショナリ・ビューに示されるcrosseditionトリガーは、現行エディションの実オブジェクトです。
起動できるトリガーの種類は、トリガーするDML文のカテゴリによって異なります。
カテゴリは、次のとおりです。
注意: SQLINSERT 文にAPPEND ヒントを指定してもcrosseditionトリガーの起動を防ぐことはできません。APPEND ヒントの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。 |
forward crosseditionトリガーSQLは、次のいずれかの方法で実行されるSQLです。
forward crosseditionトリガー本体から直接起動
forward croseditionトリガーのローカル・サブプログラムが起動された場合のみ、このカテゴリには、起動されたサブプログラムのSQLが含まれます。
apply_crossedition_trigger
パラメータに対してNULL
以外の値を指定してDBMS_SQL
.PARSE
プロシージャを起動
apply_crossedition_trigger
パラメータに対して唯一有効なNULL
以外の値は、forward crosseditionトリガーの非修飾名です。DBMS_SQL
.PARSE
プロシージャの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。
forward crosseditionトリガーが別のコンパイル・ユニットに含まれるサブプログラムを起動する場合、このトリガーがapply_crossedition_trigger
パラメータにNULL
以外の値が指定されたDBMS_SQL
.PARSE
プロシージャにより起動された場合のみ、このサブプログラムのSQLがforward crosseditionトリガーSQLになります。
forward crosseditionトリガーSQLは、次の条件をすべて満たすトリガーのみ起動できます。
forward crosseditionトリガーである。
現行エディションまたは現行エディションの子孫で作成された。
実行中のforward crosseditionトリガーに明示的に後続する。
reverse crosseditionトリガーSQLは、reverse crosseditionトリガー本体から直接実行されるSQLです。reverse croseditionトリガーのローカル・サブプログラムが起動された場合のみ、このカテゴリには、起動されたサブプログラムのSQLが含まれます。
reverse crosseditionトリガーSQLは、次の条件をすべて満たすトリガーのみ起動できます。
reverse crosseditionトリガーである。
現行エディションまたは現行エディションの先祖で作成された。
実行中のreverse crosseditionトリガーよりも前に明示的に実行される。
アプリケーションSQLは、crosseditionトリガーSQLを除くすべてのSQLで、次のDML文が含まれます。
DBMS_SQL
パッケージを使用してコーディングされた動的SQL DML文(これらの文の詳細は『Oracle Database PL/SQL言語リファレンス』を参照)。
Javaストアド・プロシージャおよび外部プロシージャによって実行されるDML文(これらのプロシージャがCALL
トリガーで起動された場合も含む)
アプリケーションSQLは、次の規則に従って、noncrosseditionトリガーとcrosseditionトリガーの両方を起動します。
トリガーの種類 | トリガーの起動条件 |
---|---|
noncrossedition | トリガーが現行エディションで表示可能かつ有効である。 |
forward crossedition | トリガーが現行エディションの子孫で作成された。 |
reverse crossedition | トリガーが現行エディションまたは現行エディションの祖先で作成された。 |
特定のDML文に対応してトリガーを起動するためのトリガーの条件は次のとおりです。
トリガーの種類が適切である(24.3.3.2項「起動できるトリガーの種類」参照)
選択の条件を満たしている(たとえば、DML文の種類やWHEN
句)
有効化されている
これらの提供を満たすトリガーの場合、起動順序は、FOLLOWS
およびPRECEDES
句、トリガーの種類、およびエディションに依存します。
内容は次のとおりです。
参照: トリガーの起動順序に関する概要は、『Oracle Database PL/SQL言語リファレンス』を参照してください。 |
トリガーAとBが同じタイミング・ポイントで起動されるとき、次のいずれかに該当するとAはBよりも先に起動します。
Aが明示的にBに先行する場合。
Bが明示的にAに続く場合。
この規則は次のような条件とは無関係です。
トリガーが有効か無効か。
UPDATE
OF
句に指定された列が変更されるかどうか。
WHEN
句が満たされるかどうか。
2つのトリガーが同じ種類のDML文(INSERT
、UPDATE
またはDELETE
)に関連付けられているかどうか。
トリガーのタイミング・ポイントが重なっているかどうか。
明示的な先行または後続の関係がないトリガーの起動順序は予測できません。
トリガーを起動するDML文に関連付けられた各タイミング・ポイントでは、条件に合うトリガーが次の順序で起動されます。1から3ではFOLLOWS
の関係が適用され、4と5ではPRECEDES
の関係が適用されます。
非crosseditionトリガー
現行エディションで作成されたforward crosseditionトリガー
現行エディションの子孫で作成されたforward crosseditionトリガー(子孫の作成順(子、孫、その子など))
現行エディションで作成されたreverse crosseditionトリガー
現行エディションの祖先で作成されたreverse crosseditionトリガー(祖先の作成と逆順(親、その親、さらにその親など))
crosseditionトリガーは、自らが作成されたエディションを使用して実行します。crosseditionトリガーがコールするすべてのコード(パッケージ参照、PL/SQLサブプログラム・コールおよびSQL文を含む)も、crosseditionトリガーが作成されたエディションで実行します。
PL/SQLパッケージが複数のエディションで実パッケージである場合、単一セッション内であっても、パッケージの変数やその他の状態は各エディションのみで公開されます。各crosseditionトリガーおよびそれらのトリガーがコールするコードは、crosseditionトリガーが作成されたエディションを使用して実行するため、同一セッションがパッケージの複数のバージョンを同じ名前でインスタンス化することがあります。
crosseditionトリガーを作成する前に、所有者がエディション対応であり、スキーマ・オブジェクト・タイプTRIGGER
が所有者でエディション対応である必要があります。(詳細は、24.1.1.4項を参照。)
次の規則に注意しながらSQL文CREATE
TRIGGER
を使用して、crosseditionトリガーを作成します。
crosseditionトリガーは、ビューではなく表に定義する必要があります。
crosseditionトリガーには、EDITIONABLE
プロパティが必要です。
crosseditionトリガーはDMLトリガー(単純トリガーまたは複合トリガー)であることが必要です。
crosseditionトリガー本体のDML文は、静的SQL文(『Oracle Database PL/SQL言語リファレンス』を参照)、またはネイティブ動的SQL文(『Oracle Database PL/SQL言語リファレンス』を参照)のどちらかです。
crosseditionトリガーは、REVERSE
を指定しないかぎりforwardになります。(FORWARD
の指定はオプションです。)
FOLLOWS
句を使用できるのは、forward crosseditionトリガーまたは非crosseditionトリガーを作成する場合のみです。(FOLLOWS
句は、作成中のトリガーが、指定したトリガーの起動後に起動することを指定します。)
PRECEDES
句を使用できるのは、reverse crosseditionトリガーを作成する場合のみです。(PRECEDES
句は、作成中のトリガーが、指定したトリガーの起動前に起動することを指定します。)
FOLLOWS
句またはPRECEDES
句に指定するトリガーは存在している必要がありますが、有効になっていなくても、正常にコンパイルされていなくてもかまいません。
非crosseditionトリガーと同じく、crosseditionトリガーは、DISABLE
を指定しないかぎり作成された時点で有効になっています。(ENABLE
の指定はオプションです。)
ヒント: crosseditionトリガーは無効な状態で作成して、正常にコンパイルされたことを確認した後で有効にします。有効な状態で作成してからコンパイルが失敗すると、既存のアプリケーションのユーザーの操作が影響を受けます。 |
crosseditionトリガー本体の操作は多重呼出し不変(操作を複数回実行するのは冗長であり、結果は変わらない)である必要があります。
参照: crosseditionトリガーを作成するCREATE TRIGGER 文の使用方法の詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。 |
forward crosseditionトリガーの本体の操作は、予測が不可能であるため、多重呼出し不変である必要があります。
古い行に対して本体が最初に実行されるコンテキスト。
可能性は次のとおりです。
祖先エディションのユーザーが、トリガー(予期せぬ変更)を起動するDML文を実行するとき
定義をトリガーする変換を適用するとき
変換の適用の詳細は、24.3.5項を参照してください。
本体が古い行それぞれについて何回実行されるか。
内容は次のとおりです。
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 は必須です。これらはオプティマイザにより必ず使用されます。 |
例24-5はAPPLYING_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);
例24-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 /* Trigger is running because of serendipitous change. Insert new row into table2 unless it is 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 /* Trigger is running because you are applying transform. If tranform has not yet inserted new row in table2, insert new row; otherwise, update new 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 croseditionトリガーの本体に含まれ、それらの表の行にトリガーが定義された表の行との1対1の対応がない場合、次の状況を正しく処理するためのロック・メカニズムを本体コードに実装する必要があります。
祖先エディションの複数のユーザーが、トリガーの定義されている表に対するDML文を同時に発行する状況。
祖先エディションのユーザーのうち、少なくとも1人が、トリガーの定義されている表に対するDML文を発行する状況。
アップグレードしているアプリケーションを構成するデータベース・オブジェクトを(新しいエディションで)再定義した後、アプリケーション・データを(古いエディションで)アップグレード前の表現から(新しいエディションで)アップグレード後の表現に変換する必要があります。この変換の規則はトランスフォームと呼ばれ、これらはforward crosseditionトリガーにより定義されます。(forward crosseditionトリガーの詳細は、24.3.1項を参照。)
古い行の一部は、予期せぬ変更、つまり、forward crosseditionトリガーが起動したアップグレード前のアプリケーションのユーザーが行った変更により、新しい行にトランスフォームされている可能性があります。しかし、予期せぬ変更によりトランスフォームされなかった行はすべてアップグレード前の表現のままです。古い行がすべて新しい行に確実にトランスフォームされるようにするには、アプリケーション・データに格納されている表で定義したトランスフォームを適用する必要があります。
トランスフォームを適用する方法には次の3通りがあります。
トランスフォームを定義しているトリガーを、表のすべての行に対して一度に1行ずつ起動します。
トリガーを起動するかわりに、トリガーで行われる内容をより速く処理するSQL文を実行し、そのトリガーに続くトリガーがあれば起動します。
表全体を置換した場合、または新しい表を作成した場合は、最初の方法より2番目の方法をお薦めします。
プロシージャDBMS_EDITIONS_UTILITIES
.SET_NULL_COLUMN_VALUES_TO_EXPR
を起動し、メタデータ操作を使用して、トランスフォームを新規列に適用します。
この3番目の方法の場合、インストール時間は最も短くなりますが、トランスフォームを表す式に関する制限があり、メタデータが実データによって置換されるまで新規列の問合せが遅くなります。
次の場所において、メタデータは実データによって置換されます。
更新される個別列要素内。
オンライン表再定義を使用して表が圧縮されるすべての列要素内。
DBMS_EDITIONS_UTILITIES
.SET_NULL_COLUMN_VALUES_TO_EXPR
プロシージャの構文、セマンティクスおよび制限の詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。
トランスフォームを適用する最初の2つの方法の場合、DBMS_SQL
.PARSE
プロシージャ、またはDBMS_PARALLEL_EXECUTE
パッケージのサブプログラムを起動します。大量のデータがある場合は2番目の方法をお薦めします。このサブプログラムを使用すると、大容量の表のデータを並列で増分的に更新することができます。これは次の2つの手順で行われます。
表の行をグループ化して小さなチャンクに分けます。
必要なUPDATE
文を並列でチャンクに適用し、1チャンクの処理が終了するたびにコミットします。
この利点は次のとおりです。
表全体のロックではなく、相対的に短い時間で一度に1セットの行のみをロックする。
操作全体が完了する前に問題が発生してもそれまでに処理した内容が失われない。
DBMS_SQL
.PARSE
プロシージャとDBMS_PARALLEL_EXECUTE
サブプログラムの両方で、apply_crossedition_trigger
、fire_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無名ブロックを指定します。
参照:
|
トランスフォームの適用中に更新内容が消失するのを防ぐには、次の手順を使用します。
crosseditionトリガーを有効化します。
影響を受ける表への保留中の変更がコミットまたはロールバックされるまで待機します。
プロシージャDBMS_UTILITY
.WAIT_ON_PENDING_DML
を使用します。このプロシージャの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。
トランスフォームを適用します。
注意: このシナリオでは、forward crosseditionトリガーが変更するのはそれが定義された表のみですが、リスクを説明するには十分です。crosseditionトリガーがまだ有効になっていないときに、セッション1がUPDATE 文を表に対して発行し、次にセッション2がcrosseditionトリガーを有効にし、すぐにトランスフォームを適用するとします。
セッション1とセッション2の両方が同じ行(行n)を変更しようとすると競合状態が発生する可能性があります。どちらのセッションが先に行nに到達するかは運次第です。最初に到達したセッションがその変更をコミットしてロックを解放するまで、2番目に行nに到達したセッションは待機する必要があるとしても、両方の更新は成功します。 問題は、セッション2が競合に勝った場合に起こります。そのSQL文はトリガーが有効になった後にコンパイルされたため、その文を実装するプログラムはトリガー・アクションも実装します。そのため、目的のアップグレード後の列の値は列nに設定されます。ここでセッション1が行nに到達しました。このSQL文はトリガーが有効になる前にコンパイルされたため、この文を実装するプログラムはトリガー・アクションを実装しません。そのため、セッション2がアップグレード後の列に設定した値は変更されず、セッション1が行nを更新する前のソース列の値を反映します。つまり、セッション1の更新の目的の副作用が消失します。 |
crosseditionトリガーを削除するには、DROP
TRIGGER
文を使用します。詳細は『Oracle Database PL/SQL言語リファレンス』を参照してください。また、DROP
EDITION
文でCASCADE
句を使用して、これらが実であるエディションを削除することにより、crosseditionトリガーを削除できます。エディションの削除の詳細は、24.1.8項を参照してください。
crosseditionトリガーは次の場合に削除します。
アプリケーション・アップグレードをロールバックしている(アップグレード後のエディションを削除している)場合。
アプリケーションのアップグレードが完了し、すべてのユーザーがアップグレード後のエディションを使用できるようにしている場合。
すべてのセッションでアップグレード後のエディションが使用されている場合は、forward crosseditionトリガーを削除できます。ただし、reverse crosseditionトリガーを削除する前に、古い列の制約をすべて無効化、または削除する必要があります。
制約を無効化または削除するには、ALTER
TABLE
文にDISABLE
CONSTRAINT
またはDROP
CONSTRAINT
句を付けて使用します。ALTER
TABLE
文の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。
内容は次のとおりです。
表24-1は、エディションに関する情報を表示する静的データ・ディクショナリ・ビューについて簡単に説明しています。特定のビューの詳細は、『Oracle Database言語リファレンス』を参照してください。
表24-1 エディション情報を含む*_ディクショナリ・ビュー
注意: *_OBJECTS および*_OBJECTS_AE に含まれる依存オブジェクトが、表23-2の操作によって無効化されるのは、次のいずれかの後のみです。
|
表24-2は、エディショニング・ビューに関する情報を表示する静的データ・ディクショナリ・ビューについて簡単に説明しています。特定のビューの詳細は、『Oracle Database言語リファレンス』を参照してください。
表24-2 エディショニング・ビュー情報を含む*_ディクショナリ・ビュー
ビュー | 説明 |
---|---|
|
エディショニング・ビューを含む、現行エディションで表示可能なデータベースのすべてのビューを示します。 |
|
現行エディションで表示可能なデータベースのすべてのエディショニング・ビューを示します。エディショニング・ビューと実表の関係を表示するときに役立ちます。 |
|
すべてのエディションにおけるデータベース内のすべてのエディショニング・ビューのすべての実オブジェクトを示します。 |
|
現行エディションで表示可能なデータベースのすべてのエディショニング・ビューの列を示します。エディショニング・ビューの列とマッピング先の表の列との関係を表示するときに役立ちます。 |
|
すべてのエディションのデータベースにあるすべてのエディショニング・ビューの列を示します。 |
*_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トリガーは、現行エディションの実オブジェクトです。
実行される一連のcrosseditionトリガーが異なる場合、子カーソルを共有することはできません。動的パフォーマンス・ビューV$SQL_SHARED_CURSOR
およびGV$SQL_SHARED_CURSOR
には、これに該当するかどうかを示すCROSSEDITION_TRIGGER_MISMATCH
列があります。V$SQL_SHARED_CURSOR
の詳細は、『Oracle Databaseリファレンス』を参照してください。
EBRを使用して、アプリケーションをオンラインでアップグレードするには、まず、アプリケーションを準備する必要があります。
アプリケーション・ユーザーおよび適切なスキーマ・オブジェクト・タイプをスキーマ内でエディション対応にします。
エディショニング・ビューを作成(次の手順)するスキーマでは、タイプVIEW
はエディション対応である必要があります。
詳細は、24.1.1.4項を参照してください。
エディショニング・ビューを使用するようにアプリケーションを準備します。
詳細は、24.5.1項を参照してください。
エディショニング・ビューを表示し、EBRを使用して、アプリケーションをオンラインで必要な回数、アップグレードすることができます。アップグレードのたびに、次のようにしてください。
再定義するオブジェクトのタイプがすべてエディション対応である場合(表はエディション対応ではありません)は、24.5.2項「エディションのみを使用するEBRの手順」の手順を使用します。
1つ以上の表の構造を変更するとき、その間に他のユーザーがそれらの表のデータを変更できなくてもよい場合は、24.5.3項「エディショニング・ビューを使用するEBRの手順」の手順を使用します。
1つ以上の表の構造を変更するとき、その間に他のユーザーがそれらの表のデータを変更できる必要がある場合は、24.5.4項「crosseditionトリガーを使用するEBRの手順」の手順を使用します。
内容は次のとおりです。
1つ以上の表を使用するアプリケーションでは、エディショニング・ビューで各表がカバーされる必要があります。エディショニング・ビューは、次のすべての記述が正しい場合にのみ、表をカバーします。
アプリケーション内の通常オブジェクトはすべて、エディショニング・ビューを通じてのみ、表を参照できます。(通常オブジェクトは、エディショニング・ビューまたはcrosseditionトリガー以外のすべてのオブジェクトです。エディショニング・ビューとcrosseditionトリガーは表を参照する必要があります。)
アプリケーション・ユーザーは、表ではなく、エディショニング・ビューに対してのみオブジェクト権限を付与されます。
仮想プライベート・データベース(VPD)ポリシーは、表ではなく、エディショニング・ビューにのみアタッチされます。(日常的な監査、およびファイングレイン監査(FGA)ポリシーは、表にのみアタッチされます。)
エディショニング・ビューが実オブジェクト化された場合、VPDポリシーのコピーは実オブジェクト化されたエディショニング・ビューにアタッチされます。(ポリシーは名前と、アタッチ先オブジェクトにより一意に識別されます。)ポリシー・ファンクションも実オブジェクト化されている場合、このポリシーのコピーは実オブジェクト化されたポリシー・ファンクションを使用します。それ以外の場合は元のポリシー・ファンクションを使用します。
VPDポリシーを示す静的なデータ・ディクショナリ・ビュー*_POLICIES
は、エディションに応じて、異なる結果を表示することができます。
参照:
|
既存のアプリケーションがエディショニング・ビューを使用していない場合は、使用する各表に対して次の手順を実行して、エディショニング・ビューを使用できるようにアプリケーションを準備します。
表に新しい名前を付けます(現在の表名をエディショニング・ビューに付けるためです)。
新しい名前は、元の名前に関連したものとし、変更履歴を示すようにしてください。たとえば、元の表名がData
の場合、新しい表名をData_1
とすることができます。
(オプション)表の各列に新しい名前を付けます。
このときも、新しい名前は、元の名前に関連したものとし、変更履歴を示すようにしてください。たとえば、Name
およびNumber
をName_1
およびNumber_1
のように変更できます。
名前を変更した列に依存するトリガーはここで無効になります。詳細は、表23-2でALTER
TABLE
table
RENAME
column
の項目を参照してください。
エディショニング・ビューを作成し、表の元の名前を付けます。
詳細は、24.2.1項を参照してください。
エディショニング・ビューには表の元の名前が付けられるため、その表名を参照しているオブジェクトがエディショニング・ビューを参照するようになります。
トリガーが表に定義されている場合は、トリガーを削除してから、作成時に使用したコードを再実行します。
こうすることで、表に定義されていたトリガーが、エディショニング・ビューに対して定義されます。
VPDポリシーが表にアタッチされている場合は、このポリシーとポリシー・ファンクションを削除してから、作成時に使用したコードを再実行します。
これにより、表にアタッチされていたVPDポリシーが、エディショニング・ビューにアタッチされます。
すべてのアプリケーション・ユーザーから、表に対するすべてのオブジェクト権限を取り消します。
表に対し、どのアプリケーション・ユーザーがどのオブジェクト権限を持っているかを確認するには、次の問合せを使用します。
SELECT GRANTEE, PRIVILEGE
FROM DBA_TAB_PRIVS
WHERE TABLE_NAME='table_name';
手順6で取り消された権限すべてについて、エディショニング・ビューで同じ権限を付与します。
表を参照するプライベート・シノニムを所有するユーザーごとに、タイプSYNONYM
がスキーマ内でエディション対応であるよう指定し、エディションを有効化します(詳細は、24.1.1.4項を参照)。
表を参照するプライベート・シノニムの所有者に、これらのシノニムの再作成が必要であることを通知します。
次の手順は、再定義するすべてのオブジェクトがエディション化(定義は24.1.1項を参照)されている場合のみ使用します。表はエディション・オブジェクトではありません。
新しいエディションを作成します。
詳細は、24.1.2項を参照してください。
新しいエディションをセッション・エディションにします。
詳細は、24.1.6.2項を参照してください。
アプリケーションのエディション・オブジェクトに必要な変更を行います。
すべてのオブジェクトが有効であることを確認します。
静的データ・ディクショナリ*_OBJECTS_AE
を問い合せます。これは、すべてのエディションにおけるデータベース内のすべての実オブジェクトを示します。無効オブジェクトが残っている場合は、任意のUTL_RECOMP
サブプログラム(『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照)を使用して再コンパイルします。
変更内容が意図したように機能していることを確認します。
機能している場合は、手順6に進みます。
そうでない場合は、さらに変更を続ける(手順3に戻る)か、またはアプリケーション・アップグレードをロールバックします(手順については、24.5.5項を参照)。
新しいエディション(アップグレードされたアプリケーション)をすべてのユーザーに対して使用可能にします。
詳細は、24.1.5項を参照してください。
古いエディション(元のアプリケーション)をリタイアさせ、SYS
以外のすべてのユーザーがアップグレードされたアプリケーションのみを使用するようにします。
詳細は、24.1.7項を参照してください。
例24-6は、ここで説明した手順を使用して、非常に単純なPL/SQLプロシージャを変更する方法を示します。
例24-6 非常に単純なプロシージャのEBR
この例で使用するPL/SQLプロシージャを作成します。
CREATE OR REPLACE PROCEDURE hello IS BEGIN DBMS_OUTPUT.PUT_LINE('Hello, edition 1.'); END hello; /
PL/SQLプロシージャを起動します。
BEGIN hello(); END; /
結果:
Hello, edition 1. PL/SQL procedure successfully completed.
プロシージャのEBRを実行します。
新しいエディションを作成します。
CREATE EDITION e2 AS CHILD OF ora$base;
結果:
Edition created.
新しいエディションをセッション・エディションにします。
ALTER SESSION SET EDITION = e2;
結果:
Session altered.
プロシージャを変更します。
CREATE OR REPLACE PROCEDURE hello IS BEGIN DBMS_OUTPUT.PUT_LINE('Hello, edition 2.'); END hello; /
結果:
Procedure created.
変更内容が意図したように機能していることを確認します。
BEGIN hello(); END; /
結果:
Hello, edition 2. PL/SQL procedure successfully completed.
すべてのユーザーが新しいエディションを使用できるようにします(システム権限が必要です)。
ALTER DATABASE DEFAULT EDITION = e2;
古いエディションをリタイアさせます(システム権限が必要です)。
権限受領者のリストを表示します。
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;
1つ以上の表の構造を変更するとき、その間に他のユーザーがそれらの表のデータを変更できる必要がない場合のみ、次の手順を使用します。
新しいエディションを作成します。
詳細は、24.1.2項を参照してください。
新しいエディションをセッション・エディションにします。
詳細は、24.1.6.2項を参照してください。
新しいエディションで、エディショニング・ビューが読取り専用の場合は、読取り/書込みに変更します。
詳細は、24.2.3項を参照してください。
新しいエディションを除くすべてのエディションで、エディショニング・ビューを読取り専用にします。
アプリケーションのオブジェクトに必要な変更を行います。
すべてのオブジェクトが有効であることを確認します。
静的データ・ディクショナリ*_OBJECTS_AE
を問い合せます。これは、すべてのエディションにおけるデータベース内のすべての実オブジェクトを示します。無効オブジェクトが残っている場合は、任意のUTL_RECOMP
サブプログラム(『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照)を使用して再コンパイルします。
変更内容が意図したように機能していることを確認します。
機能している場合は、手順8に進みます。
そうでない場合は、さらに変更を続ける(手順5に戻る)か、またはアプリケーション・アップグレードをロールバックします(手順については、24.5.5項を参照)。
アップグレードされたアプリケーションをすべてのユーザーに対して使用可能にします。
詳細は、24.1.5項を参照してください。
古いエディション(元のアプリケーション)をリタイアさせ、SYS
以外のすべてのユーザーがアップグレードされたアプリケーションのみを使用するようにします。
詳細は、24.1.7項を参照してください。
1つ以上の表の構造を変更するとき、その間に他のユーザーがそれらの表のデータを変更する必要がある場合のみ、次の手順を使用します。
新しいエディションを作成します。
詳細は、24.1.2項を参照してください。
新しいエディションをセッション・エディションにします。
詳細は、24.1.6.2項を参照してください。
アプリケーションのオブジェクトに永続的な変更を行います。
たとえば、表に新しい列を追加し、新しい永続サブプログラムを作成します。
ここで、変更したオブジェクトに依存するオブジェクトが無効になることがあります。詳細は、表23-2を参照してください。
すべてのオブジェクトが有効であることを確認します。
静的データ・ディクショナリ*_OBJECTS_AE
を問い合せます。これは、すべてのエディションにおけるデータベース内のすべての実オブジェクトを示します。無効オブジェクトが残っている場合は、任意のUTL_RECOMP
サブプログラム(『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照)を使用して再コンパイルします。
一時オブジェクト、すなわちcrosseditionトリガー(無効状態)とトリガーで必要なサブプログラムを作成します。
詳細は、24.3.4項を参照してください。
reverse crosseditionトリガーが必要になるのは、手順10(オプション)を実行する場合のみです。
crosseditionトリガーが正常にコンパイルされたら、crosseditionトリガーを有効にします。
ALTER
TRIGGER
文にENABLE
オプションを付けて使用します。この文の詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。
保留中の変更がコミットまたはロールバックされるまで待機します。
プロシージャDBMS_UTILITY
.WAIT_ON_PENDING_DML
を使用します。このプロシージャの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。
トランスフォームを適用します。
詳細は、24.3.5項を参照してください。
注意: この手順が既存の行を処理した後で、祖先エディションのユーザーが同じ行のデータを更新、挿入または削除するかどうかを予測することはできません。 |
変更内容が意図したように機能していることを確認します。
機能している場合は、手順10に進みます。
そうでない場合は、さらに変更を続ける(手順3に戻る)か、またはアプリケーション・アップグレードをロールバックします(手順については、24.5.5項を参照)。
(オプション)セッション・エディションのUSE
権限を、アップグレードしたアプリケーションの初期のユーザーに付与します。
詳細は、24.1.4項を参照してください。
アップグレードされたアプリケーションをすべてのユーザーに対して使用可能にします。
詳細は、24.1.5項を参照してください。
制約を無効化、または削除してから、croseditionトリガーを削除します。
詳細は、24.3.6項を参照してください。
古いエディション(元のアプリケーション)をリタイアさせ、SYS
以外のすべてのユーザーがアップグレードされたアプリケーションのみを使用するようにします。
詳細は、24.1.7項を参照してください。
アプリケーション・アップグレードをロールバックするには、次のようにします。
新しい表の列を作成したアップグレードをロールバックする場合
未使用の列が占めている領域を再利用するには、次のようにします。
未使用の列の値をNULL
に設定します。
この操作を行っている間に、他のユーザーをロックアウトしてしまわないようにするには、DBMS_PARALLEL_EXECUTE
プロシージャを使用します(『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照)。
未使用の列をUNUSED
に設定します。
ALTER
TABLE
文(『Oracle Database SQL言語リファレンス』を参照)をSET
UNUSED
句(『Oracle Database SQL言語リファレンス』を参照)とともに使用します。
表を縮小します。
ALTER
TABLE
文(『Oracle Database SQL言語リファレンス』を参照)をSHRINK
SPACE
句(『Oracle Database SQL言語リファレンス』を参照)とともに使用します。
この例は、エディション、エディショニング・ビュー、forward crosseditionトリガーおよびreverse crosseditionトリガーを使用します。
内容は次のとおりです。
注意: アプリケーションのアップグレードにEBRを使用する前に、このアプリケーションで使用されるスキーマすべてについてエディションを有効化する必要があります。詳細は、24.1.1.4項を参照してください。 |
既存のアプリケーション(アップグレード対象のアプリケーション)は、トリガーが定義された1つの表で構成されています。このアプリケーションは例24-7に従って作成されたものです。
例24-7 既存のアプリケーションの作成
表を作成します。
CREATE TABLE Contacts( ID NUMBER(6,0) CONSTRAINT Contacts_PK PRIMARY KEY, Name VARCHAR2(47), Phone_Number VARCHAR2(20) );
表にデータを移入します(例は示されていません)。
表にトリガーを作成する準備をします。
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; /
トリガーを作成します。
CREATE TRIGGER Contacts_BI BEFORE INSERT ON Contacts FOR EACH ROW BEGIN :NEW.ID := Contacts_Seq.NEXTVAL; END; /
例24-8は、データ移入後の表Contacts
を示しています。
例24-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トリガー(表の再定義中に他のユーザーが表のデータを変更する必要があるため)です。
例24-9は、新しいエディションでエディショニング・ビューを作成する方法を示します。Contacts
表を再定義している間、エディショニング・ビューを使用して他のユーザーがその表にアクセスします。
例24-9 既存の表のエディショニング・ビューの作成
表に新しい名前を付けます(現在の表名をエディショニング・ビューに付けるためです)。
ALTER TABLE Contacts RENAME TO Contacts_Table;
(オプション)表の列に新しい名前を付けます。
ALTER TABLE Contacts_Table RENAME COLUMN Name TO Name_1; ALTER TABLE Contacts_Table RENAME COLUMN Phone_Number TO Phone_Number_1;
エディショニング・ビューを作成します。
CREATE OR REPLACE EDITIONING VIEW Contacts AS SELECT ID ID, Name_1 Name, Phone_Number_1 Phone_Number FROM Contacts_Table;
トリガーContacts_BI
を表からエディショニング・ビューに移動します。
DROP TRIGGER Contacts_BI; CREATE TRIGGER Contacts_BI BEFORE INSERT ON Contacts FOR EACH ROW BEGIN :NEW.ID := Contacts_Seq.NEXTVAL; END; /
例24-10では、既存のアプリケーション(24.5.7.1項内)をアップグレードするエディションを作成し、新しいエディションをセッション・エディションにして、新しいエディションが実際にセッション・エディションであることをチェックする方法を示します。
例24-10 アプリケーションをアップグレードするエディションの作成
新しいエディションを作成します。
CREATE EDITION Post_Upgrade AS CHILD OF Ora$Base;
新しいエディションをセッション・エディションにします。
ALTER SESSION SET EDITION = Post_Upgrade;
セッション・エディションをチェックします。
SELECT SYS_CONTEXT('Userenv', 'Current_Edition_Name') "Current_Edition" FROM DUAL;
結果:
Current_Edition ----------------------------------------------------------------------------- POST_UPGRADE 1 row selected.
例24-11は、Post_Upgrade
エディションで、物理表に新しい列を追加し、列の追加により無効化されたトリガーを再コンパイルする方法を示します。エディショニング・ビューContacts
が表の列を適切な論理名で選択するように、このエディショニング・ビューを置換する方法を示します。
例24-11 表の変更とエディショニング・ビューの置換
物理表に新しい列を追加します。
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です。)
無効化されたトリガーを再コンパイルします。
ALTER TRIGGER Contacts_BI COMPILE REUSE SETTINGS;
エディショニング・ビューを置換して、このエディショニング・ビューが置換列を適切な論理名で選択するようにします。
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;
例24-12は、Post_Upgrade
エディションで、forward crosseditionトリガーにより使用されるプロシージャを2つ作成し、無効な状態のforward crosseditionトリガーとreverse crosseditionトリガーの両方を作成してから、これらを有効化する方法を示します。
例24-12 crosseditionトリガーの作成と有効化
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; /
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; /
無効な状態の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; /
forward crosseditionトリガーを有効化します。
ALTER TRIGGER Contacts_Fwd_Xed ENABLE;
無効な状態の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; /
reverse crosseditionトリガーを有効化します。
ALTER TRIGGER Contacts_Rvrs_Xed ENABLE;
保留中の変更がコミットまたはロールバックされるまで待機します。
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パッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。
例24-13は、Post_Upgrade
エディションで、トランスフォームを適用する方法を示します。
例24-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; /
例24-14は、Post_Upgrade
エディションで、変更が意図したとおりに機能しているかどうかをチェックする方法を示します。例24-14と例24-8を比較してください。
例24-14 変更された表のデータ表示
列が読みやすくなるように書式設定します。
COLUMN ID FORMAT 999 COLUMN Last_Name FORMAT A15 COLUMN First_Name FORMAT A15 COLUMN Country_Code FORMAT A12 COLUMN Phone_Number FORMAT A12
問合せ:
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.