エディションベースの再定義を使用すると、アプリケーションの使用中にそのデータベース・コンポーネントをアップグレードでき、停止時間を最小化あるいは排除することができます。
使用中にアプリケーションをアップグレードするには、アプリケーションを構成するデータベース・オブジェクトをコピーし、コピーしたオブジェクトを分離した状態で再定義します。変更内容はアプリケーションのユーザーには影響しません。ユーザーは変更されていないアプリケーションの実行を継続します。変更内容が正しいことを確認したら、アップグレードしたアプリケーションをすべてのユーザーが使用できるようにします。
エディションベースの再定義では、1つ以上のコンポーネント機能を使用します。使用する機能と停止時間は次の要素によって異なります。
再定義するデータベース・オブジェクトの種類
データベース・オブジェクトの再定義中に、ユーザーがそのデータベース・オブジェクトをどの程度使用できるか
以前のアプリケーションを使用しているユーザーがいるときに、アップグレードしたアプリケーションを他のユーザーが使用できるようにするかどうか
データベース・オブジェクトをコピーし、コピーしたデータベース・オブジェクトを分離した状態で再定義するには、常にエディション機能を使用します。この章で説明するオンラインでのアプリケーション・アップグレード手順がエディションベースの再定義と呼ばれるのはこのためです。
再定義するすべてのオブジェクトのオブジェクト・タイプがエディション対応(定義は「エディション対応、およびエディション非対応スキーマ・オブジェクト・タイプ」を参照)の場合、使用する機能はエディションのみです。
表はエディション対応タイプではありません。1つ以上の表の構造を変更する場合は、エディショニング・ビュー機能も使用します。
表の構造を変更している間、他のユーザーがその表のデータを変更する必要がある場合は、forward crosseditionトリガーも使用します。アップグレード前のアプリケーションとアップグレード後のアプリケーションが同時に通常使用(ホット・ロールオーバー)されている場合、reverse crosseditionトリガーも使用します。crosseditionトリガーはアプリケーションの永続的な要素ではありません。全ユーザーがアップグレード後のアプリケーションを使用するようになったら削除します。
内容は次のとおりです。
エディションはスキーマ・オブジェクトではなく、所有者もありません。エディションは1つのネームスペースに作成されます。複数のエディションがデータベースに共存することができます。
データベースには少なくとも1つのエディションが必要です。新規作成またはアップグレードされたOracle Databaseはすべて、ora$base
という名前の1つのエディションから開始されます。
内容は次のとおりです。
エディション・オブジェクトは、エディション対応タイプとエディションが有効化された所有者の両方を持つスキーマ・オブジェクトです。(エディション対応タイプは持っているが、エディションが有効化された所有者を持たないスキーマ・オブジェクトは潜在的エディションです。)この場合、そのエディションに対してはこのコピーのみが表示可能です。
非エディション・オブジェクトは、非エディション・タイプのスキーマ・オブジェクトです。エディションは、非エディション・オブジェクトの独自のコピーを持つことはできません。非エディション・オブジェクトは、すべてのエディションで同一です。また、どのエディションでも表示できます。
エディション・オブジェクトは、そのOBJECT_NAME
、OWNER
、およびEDITION_NAME
により一意に識別されます。非エディション・オブジェクトは、そのOBJECT_NAME
およびOWNER
により(EDITION_NAME
はNULL
)一意に識別されます(厳密に言えば、オブジェクトを一意に識別するにはオブジェクトのNAMESPACE
も必要ですが、オブジェクトを参照する文では暗黙的または明示的にNAMESPACE
が指定されるので、これは無視しても構いません)。
オブジェクトのOBJECT_NAME
、OWNER
、およびEDITION_NAME
は、静的ディクショナリ・ビュー*_OBJECTS
および*_OBJECTS_AE
に表示できます(表19-1を参照)。
オブジェクトのEDITION_NAME
を知らなくても、このオブジェクトを参照できます(知っていても、指定できません)。参照のコンテキストで、エディションを暗黙的に指定します。コンテキストがデータ定義言語(DDL)文である場合、エディションは、このコマンドを発行したセッションの現行エディションです(現行エディションの詳細は、「現行エディションとセッション・エディション」を参照)。コンテキストがソース・コードである場合、エディションはオブジェクトが実オブジェクトであるものです(「継承オブジェクトと実オブジェクト」を参照)。
内容は次のとおりです。
SYNONYM
VIEW
すべてのPL/SQLオブジェクト型:
FUNCTION
LIBRARY
PACKAGE
およびPACKAGE
BODY
PROCEDURE
TRIGGER
TYPE
およびTYPE
BODY
その他のスキーマ・オブジェクト・タイプはすべて非エディション対応です。表は非エディション対応タイプの一例です。
エディション対応タイプのスキーマ・オブジェクトは、その所有者に対してエディションが有効化されている場合はエディション化されます。それ以外の場合は、潜在的エディション・オブジェクトです。
非エディション対応タイプのスキーマ・オブジェクトは、その所有者に対してエディションが有効化されていても、常にエディション化できません。表は非エディション・オブジェクトの一例です。
注意: この規則には1つ例外があります。SYNONYM はエディション対応タイプですが、パブリック・シノニムは非エディション・オブジェクトです。 |
非エディション・オブジェクトは、エディション・オブジェクトに依存できません。
次に例を示します。
表は、エディションが有効化されているユーザーを所有者とするユーザー定義のデータ型(コレクションまたは抽象データ型(ADT))の列を持つことはできません。
非エディション・サブプログラムは、エディションが有効化されているユーザーを所有者とするサブプログラムを静的に参照することはできません。
この規則の理由については、「参照されているオブジェクトの実オブジェクト化」を参照してください。
ADTをエディション化し、同時に進化させることはできません。
型進化の詳細は、『Oracle Databaseオブジェクト・リレーショナル開発者ガイド』を参照してください。
エディション・オブジェクトを、FOREIGN
KEY
制約の始点、または終点にすることはできません。
この規則が影響するエディション・オブジェクトは、エディション化されたビューのみです。エディション化されたビューとは、通常のビュー、またはエディショニング・ビューのどちらかです。
ユーザーに対してエディションを有効化するには、CREATE
USER
、またはALTER
USER
文のENABLE
EDITIONS
句を使用します。
静的データ・ディクショナリ・ビューDBA_USERS
またはUSER_USERS
のEDITIONS_ENABLED
列に、エディションが有効化されているユーザーが示されます。
エディションの有効化は遡及的で、これを元に戻すことはできません。ユーザーに対してエディションが有効化されている場合、このユーザーが所有している、または将来所有するエディション対応タイプのオブジェクトはすべて、エディション・オブジェクトです。次のようにして、FORCE
を指定しないかぎり、エディション化されていない依存オブジェクトを持ち、潜在的エディション・オブジェクトを所有するユーザーに対してエディションを有効化することはできません。
ALTER USER user_name ENABLE EDITIONS FORCE;
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;
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
に対してエディションを有効化することができます。
1つ以上の進化したADTを所有するユーザーに対してエディションを有効化することはできません。有効化しようとすると、エラーORA-38820が発生します。ADTが表への依存性を持っていない場合、ALTER
TYPE
RESET
文を使用して、バージョンを1にリセットすることにより、それ以上、表が進化するとみなされないようにすることができます(ADTのバージョンを1にリセットすると、これに依存するものは無効化されます。)
参照:
|
エディションを作成するには、SQL文CREATE
EDITION
を使用します。
エディションは既存のエディションの子として作成する必要があります。CREATE
EDITION
文によって作成される最初のエディションの親はora$base
です。次の文によって、ora$base
の子としてエディションe2
が作成されます。
CREATE EDITION e2
(例19-1などでこの文が使用されています。)
Oracle Database 11gリリース2では、エディションの子は最大で1つです。
エディションの子孫は、エディションの子、子の子、その子などを指します。エディションの祖先は、エディションの親、親の親、その親などを指します。ルート・エディションには親はありません。また、リーフ・エディションには子はありません。
参照: 使用するための権限も含む、CREATE EDITION文の詳細は、 『Oracle Database SQL言語リファレンス』 を参照してください。 |
各データベース・セッションで一度に使用されるエディションは1つのみです。作成時に子エディションは、親エディションで表示可能なデータベースのすべてのエディション・オブジェクトを親エディションから継承します。各継承オブジェクトは子エディションで表示可能です。
継承オブジェクトは、変更時にコピー、すなわち実オブジェクト化されます。つまり、子エディションのユーザーがDDL文(DROP
以外)で継承オブジェクトを参照すると、継承オブジェクトはコピーされ、DDL文はコピー(実オブジェクト)のみに作用します。親エディション内の未変更のオブジェクトは、子エディションでは表示可能ではなくなります。
注意: DDL文CREATE OR REPLACE object に効果がない場合、object は実オブジェクト化されません(詳細は、「依存オブジェクトの無効化」を参照)。DDL文ALTER object COMPILE は、常にobject を実オブジェクト化します。 |
例19-1は、エディションora$base
でプロシージャhello
を作成してから、ora$base
の子としてエディションe2
を作成します。e2
がhello
を起動するときは、継承プロシージャを起動します。このとき、e2
はhello
を変更して、実オブジェクト化します。エディションora$base
のプロシージャhello
は変更されず、e2
には表示されなくなります。ここで、e2
がhello
を起動するときは、実プロシージャを起動します。
例19-1 継承オブジェクトと実オブジェクト
親エディションでプロシージャを作成します。
CREATE OR REPLACE PROCEDURE hello IS BEGIN DBMS_OUTPUT.PUT_LINE('Hello, edition 1.'); END hello; /
親エディションでプロシージャを起動します。
BEGIN hello(); END; /
結果:
Hello, edition 1.
PL/SQL procedure successfully completed.
子エディションを作成します。
CREATE EDITION e2;
子エディションを使用します。
ALTER SESSION SET EDITION = e2;
ALTER
SESSION
SET
EDITION
の詳細は、「セッション・エディションの変更」を参照してください。
子エディションで、次のプロシージャを起動します。
BEGIN hello(); END; /
子エディションは、親エディションからプロシージャを継承します。子エディションにより、継承したプロシージャが起動されます。結果:
Hello, edition 1.
PL/SQL procedure successfully completed.
子エディションでプロシージャを変更します。
CREATE OR REPLACE PROCEDURE hello IS
BEGIN
DBMS_OUTPUT.PUT_LINE('Hello, edition 2.');
END hello;
/
子は、プロシージャの独自のコピーのみ変更します。子のコピーは実オブジェクトです。
プロシージャを起動します。
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.
内容は次のとおりです。
子エディションのユーザーが継承オブジェクトを削除すると、そのオブジェクトは子エディションでは表示されなくなりますが、親エディションでは引き続き表示可能です。
例19-2は、エディションora$base
でプロシージャgoodbye
を作成してから、ora$base
の子としてエディションe2
を作成します。e2
でgoodbye
が削除されると、e2はgoodbyeを起動できなくなりますが、ora$base
では起動できます(使用するための権限も含む、DROP
PROCEDURE
文の詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください)。
例19-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
を使用します。
ALTER SESSION SET EDITION = e2;
ALTER
SESSION
SET
EDITION
はトップレベルのSQL文である必要があります。詳細は、「セッション・エディションの変更」を参照してください。
e2
で、次のプロシージャを起動します。
BEGIN goodbye; END; /
e2
により、継承されたプロシージャが起動されます。
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
親に戻ります。
ALTER SESSION SET EDITION = ora$base;
親で、次のプロシージャを起動します。
BEGIN goodbye; END; /
結果:
Good-bye! PL/SQL procedure successfully completed.
e2
でプロシージャgoodbye
が削除されたため、次のようになります。
子孫では、プロシージャgoodbye
が継承されません。
goodbye
というオブジェクトはe2
で表示可能でないため、e2
では、任意のエディション対応タイプのオブジェクトをgoodbye
という名前を付けて作成できます。e2
でこのようなオブジェクトが作成された場合、e2
の子孫はこのオブジェクトを継承します。
例19-3では、e2
にgoodbye
という名前のファンクションが作成され、その後、e2
の子としてe3
という名前のエディションが作成されます。e3
でプロシージャgoodbye
(e2
で削除)を起動しようとすると、エラーが発生しますが、e3
でファンクションgoodbye
(e2
で作成)は正常に起動されます。
例19-3 削除済継承オブジェクトの名前を使用したオブジェクトの作成
e2
に戻ります。
ALTER SESSION SET EDITION = e2;
ALTER
SESSION
SET
EDITION
の詳細は、「セッション・エディションの変更」を参照してください。
e2
で、goodbye
という名前のファンクションを作成します。
CREATE OR REPLACE FUNCTION goodbye RETURN BOOLEAN IS BEGIN RETURN(TRUE); END goodbye; /
エディションe3
を作成します。
CREATE EDITION e3 AS CHILD OF e2;
エディションe3
を使用します。
ALTER SESSION SET EDITION = e3;
e3
で、プロシージャgoodbye
の起動を試行します。
BEGIN goodbye; END; /
結果:
goodbye; * ERROR at line 2: ORA-06550: line 2, column 3: PLS-00221: 'GOODBYE' is not a procedure or is undefined 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
コマンドを使用することをお薦めします。サービスのデフォルトの最初のセッション・エディションを指定するには、-t
オプションを使用します。
また、DBMS_SERVICE
.CREATE_SERVICE
またはDBMS_SERVICE
.MODIFY_SERVICE
プロシージャを使用してデータベース・サービスを作成または変更して、EDITION
属性を使用してデフォルトの最初のセッション・エディションを指定できます。
注意: Oracle Database 11gリリース2では、DBMS_SERVICE .CREATE_SERVICE およびDBMS_SERVICE .MODIFY_SERVICE プロシージャは、Oracle ClusterwareおよびOracle Restartにより管理されるデータベースで非推奨です。 |
参照:
|
データベースに接続した後で、SQL文ALTER
SESSION
SET
EDITION
を使用してセッション・エディションを変更することができます。セッション・エディションは、USE
権限のある任意のエディションに変更することができます。セッション・エディションを変更すると、現行エディションも同じセッション・エディションに変更されます。
例19-1および例19-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トリガーが起動される場合。
詳細は、「crosseditionトリガーとエディションの相互作用」を参照してください。
例19-4
のように、DBMS_SQL
.PARSEプロシージャをコールして、文を実行するエディションを指定することで、文を実行する場合。
文が実行している間、指定されたエディションが現行エディションになりますが、セッション・エディションは変更されません。DBMS_SQL
.PARSE
プロシージャの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。
例19-4では、セッション・エディションと現行エディションの名前を返すファンクションが作成されます。その後、子エディションが作成され、子エディションによってそのファンクションが2回起動されます。1回目はセッション・エディションと現行エディションは同じです。2回目は異なります。別のエディションがパラメータとしてDBMS_SQL
.PARSE
プロシージャに渡されるためです。
例19-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言語リファレンス』を参照してください。
エディションを削除するには、DROP
EDITION
文を使用します。詳細は、『Oracle Database SQL言語リファレンス』を参照してください。エディションに実オブジェクトがある場合は、実オブジェクトを削除するCASCADE
句を指定する必要があります。
DROP
EDITION
edition
CASCADE
文が正常終了前に(たとえば、停電などの理由で)中断された場合、静的データ・ディクショナリ・ビュー*_EDITIONS
には、edition
に対するUSABLE
の値がNO
であることが表示されます。このように使用できないedition
に対して実行できる唯一の操作は、DROP
EDITION
CASCADE
です。
エディションは次の場合に削除します。
アプリケーション・アップグレードをロールバックする必要がある場合。
(オプション)エディションをリタイアさせた場合。
エディションを削除できるのは、次のすべての条件に該当する場合のみです。
エディションがルート・エディション、またはリーフ・エディションである場合。
エディションがルートの場合、その子孫により継承されているオブジェクトを持っていない場合。(つまり、ルート・エディションから継承された各オブジェクトは、実オブジェクト化されたか、削除された場合)。
エディションが使用されていない場合(つまり、セッションの現行エディションまたはセッション・エディションではない場合)。
このエディションが、データベースのデフォルト・エディションではない場合。
子エディションで継承オブジェクトを明示的に実オブジェクト化するには、次のようにします。
子エディションをセッション・エディションにします。
手順は、「セッション・エディションの変更」を参照してください。
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言語リファレンス』を参照してください。
参照:
|
エディショニング・ビューを作成する前に、エディショニング・ビューの所有者に対してエディションを有効化しておく必要があります。
エディショニング・ビュー以外のビューで定義できるトリガーのタイプは、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リファレンス』を参照してください。 |
エディショニング・ビューを作成するには、SQL文CREATE
VIEW
をキーワードEDITIONING
とともに使用します。エディショニング・ビューを読取り専用にするには、WITH
READ
ONLY
を指定します。読取り/書込みにするにはWITH
READ
ONLY
を省略します。
エディショニング・ビューが読取り専用の場合、未変更アプリケーションのユーザーが実表のデータを見ることはできますが、変更することはできません。この実表は準可用性を備えています。準可用性を利用できるのは、ユーザーが読むだけで変更しない、オンライン・ディクショナリなどのアプリケーションです。実表に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文が実行されるエディションを指します。現行エディションはセッション・エディションと異なることがあります(詳細は、「現行エディションがセッション・エディションと異なる状況」を参照)。
エディションは、非crosseditionトリガーを他のエディション・オブジェクトと同じように継承します(「継承オブジェクトと実オブジェクト」を参照)。
エディションは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文に対応してトリガーを起動するためのトリガーの条件は次のとおりです。
トリガーの種類が適切である(「起動できるトリガーの種類」参照)
選択の条件を満たしている(たとえば、DML文の種類やWHEN
句)
有効化されている
これらの条件を満たすトリガーの場合、起動順序は次により決定されます。
参照: トリガーの起動順序に関する概要は、『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トリガーを作成するには、エディションが有効化されたユーザーである必要があります(ユーザーに対してエディションを有効にする方法の詳細は「ユーザーに対するエディションの有効化」を参照)。
次の規則に注意しながらSQL文CREATE
TRIGGER
を使用して、crosseditionトリガーを作成します。
crosseditionトリガーは、ビューではなく表に定義する必要があります。
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文を実行するとき
定義をトリガーする変換を適用するとき
変換の適用に関する詳細は、「アップグレード前の表現をアップグレード後の表現に変換」を参照してください。
本体が古い行それぞれについて何回実行されるか。
内容は次のとおりです。
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 は必須です。これらはオプティマイザにより必ず使用されます。 |
例19-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);
例19-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トリガーについては、「forward crosseditionトリガー」を参照してください。)
古い行の一部は、予期せぬ変更、つまり、forward crosseditionトリガーが起動したアップグレード前のアプリケーションのユーザーが行った変更により、新しい行にトランスフォームされている可能性があります。しかし、予期せぬ変更によりトランスフォームされなかった行はすべてアップグレード前の表現のままです。古い行がすべて新しい行に確実にトランスフォームされるようにするには、アプリケーション・データに格納されている表で定義したトランスフォームを適用する必要があります。
トランスフォームを適用する方法には次の2通りがあります。
トランスフォームを定義しているトリガーを、表のすべての行に対して一度に1行ずつ起動します。
トリガーを起動するかわりに、トリガーで行われる内容をより速く処理する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トリガーを削除できます。エディションの削除の詳細は、「エディションの削除」を参照してください。
crosseditionトリガーは次の場合に削除します。
アプリケーション・アップグレードをロールバックしている(アップグレード後のエディションを削除している)場合。
アプリケーションのアップグレードが完了し、すべてのユーザーがアップグレード後のエディションを使用できるようにしている場合。
すべてのセッションでアップグレード後のエディションが使用されている場合は、forward crosseditionトリガーを削除できます。ただし、reverse crosseditionトリガーを削除する前に、古い列の制約をすべて無効化、または削除する必要があります。
制約を無効化または削除するには、ALTER
TABLE
文にDISABLE
CONSTRAINT
またはDROP
CONSTRAINT
句を付けて使用します。ALTER
TABLE
文の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。
表19-1および表19-2に、静的データ・ディクショナリ・ビューを示します。各ビューには、それぞれエディションとエディショニング・ビューの情報が表示されます。各表のビューの詳細は、『Oracle Databaseリファレンス』を参照してください。
トリガーの情報を表示する静的データ・ディクショナリ・ビューは、『Oracle Databaseリファレンス』を参照してください。静的データ・ディクショナリ・ビューに示されるcrosseditionトリガーは、セッション・エディションの実オブジェクトです。
実行される一連のcrosseditionトリガーが異なる場合、子カーソルを共有することはできません。動的パフォーマンス・ビューV$SQL_SHARED_CURSOR
およびGV$SQL_SHARED_CURSOR
には、これに該当するかどうかを示すCROSSEDITION_TRIGGER_MISMATCH
列があります。V$SQL_SHARED_CURSOR
の詳細は、『Oracle Databaseリファレンス』を参照してください。
表19-1 エディション情報を含む*_ディクショナリ・ビュー
注意: *_OBJECTS および*_OBJECTS_AE に含まれる依存オブジェクトが、表18-2の操作によって無効化されるのは、次のいずれかの後のみです。
|
表19-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
にはありません。
エディションベースの再定義を使用して、アプリケーションをオンラインでアップグレードするには、まず、アプリケーションを準備する必要があります。
該当するユーザーに対してエディションを有効化します。
手順は、「ユーザーに対するエディションの有効化」を参照してください。
この手順を行う理由は、この次の手順で作成するエディショニング・ビューを所有できるのは、エディションが有効化されているユーザーのみであるためです。
エディショニング・ビューを使用するようにアプリケーションを準備します。
手順については、「アプリケーションでのエディショニング・ビューの使用準備」を参照してください。
エディショニング・ビューを表示し、エディションベースの再定義を使用して、アプリケーションをオンラインで必要な回数、アップグレードすることができます。アップグレードのたびに、次のようにしてください。
再定義するオブジェクトのタイプがすべてエディション対応である場合(表はエディション対応ではありません)は、「エディションのみを使用するエディションベースの再定義の手順」を使用します。
1つ以上の表の構造を変更するとき、その間に他のユーザーがそれらの表のデータを変更できなくてもよい場合は、「エディショニング・ビューを使用するエディションベースの再定義の手順」を使用します。
1つ以上の表の構造を変更するとき、その間に他のユーザーがそれらの表のデータを変更できるようにする必要がある場合は、「crosseditionトリガーを使用するエディションベースの再定義の手順」を使用します。
内容は次のとおりです。
1つ以上の表を使用するアプリケーションでは、エディショニング・ビューで各表がカバーされる必要があります。エディショニング・ビューは、次のすべての記述が正しい場合にのみ、表をカバーします。
アプリケーション内の通常オブジェクトはすべて、エディショニング・ビューを通じてのみ、表を参照できます。(通常オブジェクトは、エディショニング・ビューまたはcrosseditionトリガー以外のすべてのオブジェクトです。エディショニング・ビューとcrosseditionトリガーは表を参照する必要があります。)
アプリケーション・ユーザーは、表ではなく、エディショニング・ビューに対してのみオブジェクト権限を付与されます。
仮想プライベート・データベース(VPD)ポリシーは、表ではなく、エディショニング・ビューにのみアタッチされます。(日常的な監査、およびファイングレイン監査(FGA)ポリシーは、表にのみアタッチされます。)
エディショニング・ビューが実オブジェクト化された場合、VPDポリシーのコピーは実オブジェクト化されたエディショニング・ビューにアタッチされます。(ポリシーは名前と、アタッチ先オブジェクトにより一意に識別されます。)ポリシー・ファンクションも実オブジェクト化されている場合、このポリシーのコピーは実オブジェクト化されたポリシー・ファンクションを使用します。それ以外の場合は元のポリシー・ファンクションを使用します。
VPDポリシーを示す静的なデータ・ディクショナリ・ビュー*_POLICIES
は、エディションに応じて、異なる結果を表示することができます。
参照:
|
既存のアプリケーションがエディショニング・ビューを使用していない場合は、使用する各表に対して次の手順を実行して、エディショニング・ビューを使用できるようにアプリケーションを準備します。
表に新しい名前を付けます(現在の表名をエディショニング・ビューに付けるためです)。
新しい名前は、元の名前に関連したものとし、変更履歴を示すようにしてください。たとえば、元の表名がData
の場合、新しい表名をData_1
とすることができます。
(オプション)表の各列に新しい名前を付けます。
このときも、新しい名前は、元の名前に関連したものとし、変更履歴を示すようにしてください。たとえば、Name
およびNumber
をName_1
およびNumber_1
のように変更できます。
名前を変更した列に依存するトリガーはここで無効になります。詳細は、表18-2
でALTER
TABLE
table
RENAME
columnの項目を参照してください。
エディショニング・ビューを作成し、表の元の名前を付けます。
手順は、「エディショニング・ビューの作成」を参照してください。
エディショニング・ビューには表の元の名前が付けられるため、その表名を参照しているオブジェクトがエディショニング・ビューを参照するようになります。
トリガーが表に定義されている場合は、トリガーを削除してから、作成時に使用したコードを再実行します。
こうすることで、表に定義されていたトリガーが、エディショニング・ビューに対して定義されます。
VPDポリシーが表にアタッチされている場合は、このポリシーとポリシー・ファンクションを削除してから、作成時に使用したコードを再実行します。
これにより、表にアタッチされていたVPDポリシーが、エディショニング・ビューにアタッチされます。
すべてのアプリケーション・ユーザーから、表に対するすべてのオブジェクト権限を取り消します。
表に対し、どのアプリケーション・ユーザーがどのオブジェクト権限を持っているかを確認するには、次の問合せを使用します。
SELECT GRANTEE, PRIVILEGE
FROM DBA_TAB_PRIVS
WHERE TABLE_NAME='table_name';
手順6で取り消された権限すべてについて、エディショニング・ビューで同じ権限を付与します。
表を参照するプライベート・シノニムを所有するユーザーに対してエディションを有効化し(手順については、「ユーザーに対するエディションの有効化」を参照)、これらのユーザーに、シノニムを再作成する必要があることを通知します。
注意: この結果、表を参照するパブリック・シノニムはORA-00980で失敗するようになります。エディショニング・ビューでこれらを再作成することはできません(理由については、「参照されているオブジェクトの実オブジェクト化」を参照)。 |
次の手順は、再定義するすべてのオブジェクトのオブジェクト・タイプがエディション対応(定義は「エディション対応、およびエディション非対応スキーマ・オブジェクト・タイプ」を参照)である場合のみ使用します。表はエディション対応タイプではありません。
新しいエディションを作成します。
手順は、「エディションの作成」を参照してください。
新しいエディションをセッション・エディションにします。
手順は、「セッション・エディションの変更」を参照してください。
アプリケーションのエディション・オブジェクトに必要な変更を行います。
すべてのオブジェクトが有効であることを確認します。
静的データ・ディクショナリ*_OBJECTS_AE
を問い合せます。これは、すべてのエディションにおけるデータベース内のすべての実オブジェクトを示します。無効オブジェクトが残っている場合は、任意のUTL_RECOMP
サブプログラム(『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照)を使用して再コンパイルします。
変更内容が意図したように機能していることを確認します。
機能している場合は、手順6に進みます。
そうでない場合は、さらに変更を続ける(手順3に戻る)か、またはアプリケーション・アップグレードをロールバックします(手順については、「アプリケーション・アップグレードのロールバック」を参照)。
新しいエディション(アップグレードされたアプリケーション)をすべてのユーザーに対して使用可能にします。
手順は、「すべてのユーザーに対してエディションを使用可能にする」を参照してください。
古いエディション(元のアプリケーション)をリタイアさせ、SYS
以外のすべてのユーザーがアップグレードされたアプリケーションのみを使用するようにします。
手順は、「エディションのリタイア」を参照してください。
例19-6は、ここで説明した手順を使用して、非常に単純なPL/SQLプロシージャを変更する方法を示します。
例19-6 非常に単純なプロシージャのエディションベースの再定義
この例で使用する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.
プロシージャをエディションベースで再定義します。
新しいエディションを作成します。
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つ以上の表の構造を変更するとき、その間に他のユーザーがそれらの表のデータを変更できなくてもよい場合のみ、次の手順を使用します。
新しいエディションを作成します。
手順は、「エディションの作成」を参照してください。
新しいエディションをセッション・エディションにします。
手順は、「セッション・エディションの変更」を参照してください。
新しいエディションで、エディショニング・ビューが読取り専用の場合は、読取り/書込みに変更します。
手順は、「エディショニング・ビューの書込み可能性の変更」を参照してください。
新しいエディションを除くすべてのエディションで、エディショニング・ビューを読取り専用にします。
アプリケーションのオブジェクトに必要な変更を行います。
すべてのオブジェクトが有効であることを確認します。
静的データ・ディクショナリ*_OBJECTS_AE
を問い合せます。これは、すべてのエディションにおけるデータベース内のすべての実オブジェクトを示します。無効オブジェクトが残っている場合は、任意のUTL_RECOMP
サブプログラム(『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照)を使用して再コンパイルします。
変更内容が意図したように機能していることを確認します。
機能している場合は、手順8に進みます。
そうでない場合は、さらに変更を続ける(手順5に戻る)か、またはアプリケーション・アップグレードをロールバックします(手順については、「アプリケーション・アップグレードのロールバック」を参照)。
アップグレードされたアプリケーションをすべてのユーザーに対して使用可能にします。
手順は、「すべてのユーザーに対してエディションを使用可能にする」を参照してください。
古いエディション(元のアプリケーション)をリタイアさせ、SYS
以外のすべてのユーザーがアップグレードされたアプリケーションのみを使用するようにします。
手順は、「エディションのリタイア」を参照してください。
1つ以上の表の構造を変更するとき、その間に他のユーザーがそれらの表のデータを変更する必要がある場合のみ、次の手順を使用します。
新しいエディションを作成します。
手順は、「エディションの作成」を参照してください。
新しいエディションをセッション・エディションにします。
手順は、「セッション・エディションの変更」を参照してください。
アプリケーションのオブジェクトに永続的な変更を行います。
たとえば、表に新しい列を追加し、新しい永続サブプログラムを作成します。
ここで、変更したオブジェクトに依存するオブジェクトが無効になることがあります。詳細は、表18-2を参照してください。
すべてのオブジェクトが有効であることを確認します。
静的データ・ディクショナリ*_OBJECTS_AE
を問い合せます。これは、すべてのエディションにおけるデータベース内のすべての実オブジェクトを示します。無効オブジェクトが残っている場合は、任意のUTL_RECOMP
サブプログラム(『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照)を使用して再コンパイルします。
一時オブジェクト、すなわちcrosseditionトリガー(無効状態)とトリガーで必要なサブプログラムを作成します。
手順は、「crosseditionトリガーの作成」を参照してください。
reverse crosseditionトリガーが必要になるのは、手順10(オプション)を実行する場合のみです。
crosseditionトリガーが正常にコンパイルされたら、crosseditionトリガーを有効にします。
ALTER
TRIGGER
文にENABLE
オプションを付けて使用します。この文の詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。
保留中の変更がコミットまたはロールバックされるまで待機します。
プロシージャDBMS_UTILITY
.WAIT_ON_PENDING_DML
を使用します。このプロシージャの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。
トランスフォームを適用します。
手順については、「アップグレード前の表現をアップグレード後の表現に変換」を参照してください。
注意: この手順が既存の行を処理した後で、祖先エディションのユーザーが同じ行のデータを更新、挿入または削除するかどうかを予測することはできません。 |
変更内容が意図したように機能していることを確認します。
機能している場合は、手順10に進みます。
そうでない場合は、さらに変更を続ける(手順3に戻る)か、またはアプリケーション・アップグレードをロールバックします(手順については、「アプリケーション・アップグレードのロールバック」を参照)。
(オプション)セッション・エディションのUSE
権限を、アップグレードしたアプリケーションの初期のユーザーに付与します。
手順は、「一部のユーザーに対してエディションを使用可能にする」を参照してください。
アップグレードされたアプリケーションをすべてのユーザーに対して使用可能にします。
手順は、「すべてのユーザーに対してエディションを使用可能にする」を参照してください。
制約を無効化、または削除してから、croseditionトリガーを削除します。
手順は、「crosseditionトリガーの削除」を参照してください。
古いエディション(元のアプリケーション)をリタイアさせ、SYS
以外のすべてのユーザーがアップグレードされたアプリケーションのみを使用するようにします。
手順は、「エディションのリタイア」を参照してください。
アプリケーション・アップグレードをロールバックするには、次のようにします。
セッション・エディションを、アップグレード用に作成した新しいエディション以外のものに変更します。
手順は、「セッション・エディションの変更」を参照してください。
アップグレード用に作成した新しいエディションを削除します。
手順は、「エディションの削除」を参照してください。
アップグレード中に、新しい表の列を作成した場合、これらの列が占めていた領域を再利用します(手順については、「使用されていない表の列が占める領域の再利用」を参照)。
新しい表の列を作成したアップグレードをロールバックする場合
未使用の列が占めている領域を再利用するには、次のようにします。
未使用の列の値を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トリガーを使用します。
内容は次のとおりです。
注意: アプリケーションのアップグレードにエディションベースの再定義を使用する前に、このアプリケーションで使用されるスキーマすべてについてエディションを有効化する必要があります。手順は、「ユーザーに対するエディションの有効化」を参照してください。 |
既存のアプリケーション(アップグレード対象のアプリケーション)は、トリガーが定義された1つの表で構成されています。このアプリケーションは例19-7に従って作成されたものです。
例19-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; /
例19-8は、データ移入後の表Contacts
を示しています。
例19-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
のデータを変更できることが必要です。
エディションベースの再定義のすべての機能が必要になります。つまり、エディション(常に必要)、エディショニング・ビュー(表を再定義するため)、およびcrosseditionトリガー(表の再定義中に他のユーザーが表のデータを変更する必要があるため)です。
例19-8は、新しいエディションでエディショニング・ビューを作成する方法を示します。Contacts
表を再定義している間、エディショニング・ビューを使用して他のユーザーがその表にアクセスします。
例19-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; /
例19-10では、既存のアプリケーションをアップグレードするエディションを作成し、新しいエディションをセッション・エディションにして、新しいエディションが実際にセッション・エディションであることをチェックする方法を示します。
例19-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.
例19-11
は、Post_Upgradeエディションで、物理表に新しい列を追加し、列の追加により無効化されたトリガーを再コンパイルする方法を示します。エディショニング・ビューContacts
が表の列を適切な論理名で選択するように、このエディショニング・ビューを置換する方法を示します。
例19-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;
例19-12
は、Post_Upgradeエディションで、forward crosseditionトリガーにより使用されるプロシージャを2つ作成し、無効な状態のforward crosseditionトリガーとreverse crosseditionトリガーの両方を作成してから、これらを有効化する方法を示します。
例19-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パッケージおよびタイプ・リファレンス』を参照してください。
例19-13
は、Post_Upgradeエディションで、トランスフォームを適用する方法を示します。
例19-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; /
例19-14
は、Post_Upgradeエディションで、変更が意図したとおりに機能しているかどうかをチェックする方法を示します。例19-14と例19-8を比較してください。
例19-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.
変更が意図どおりに機能した場合は、「crosseditionトリガーを使用するエディションベースの再定義の手順」の手順10から13を実行することができます。