Oracle® Streams

拡張例

12c リリース1 (12.1)

B71330-02(原本部品番号:E17912-10)

2015年2月

Oracle Streams拡張例, 12c リリース1 (12.1)

B71330-02

Copyright © 2008, 2015, Oracle and/or its affiliates. All rights reserved.

原本著者:  Randy Urbano

協力者: Nimar Arora、Alan Downing、Thuvan Hoang、Tianshu Li、Jing Liu、Edwina Lu、Pat McElroy、Valarie Moore、Neeraj Shodhan、Jim Stamos、Byron Wang、Katherine Weill、Lik Wong、Jingwei Wu

このソフトウェアおよび関連ドキュメントの使用と開示は、ライセンス契約の制約条件に従うものとし、知的財産に関する法律により保護されています。ライセンス契約で明示的に許諾されている場合もしくは法律によって認められている場合を除き、形式、手段に関係なく、いかなる部分も使用、複写、複製、翻訳、放送、修正、ライセンス供与、送信、配布、発表、実行、公開または表示することはできません。このソフトウェアのリバース・エンジニアリング、逆アセンブル、逆コンパイルは互換性のために法律によって規定されている場合を除き、禁止されています。

ここに記載された情報は予告なしに変更される場合があります。また、誤りが無いことの保証はいたしかねます。誤りを見つけた場合は、オラクル社までご連絡ください。

このソフトウェアまたは関連ドキュメントを、米国政府機関もしくは米国政府機関に代わってこのソフトウェアまたは関連ドキュメントをライセンスされた者に提供する場合は、次の通知が適用されます。

U.S. GOVERNMENT END USERS: Oracle programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, delivered to U.S. Government end users are "commercial computer software" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations.As such, use, duplication, disclosure, modification, and adaptation of the programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, shall be subject to license terms and license restrictions applicable to the programs.No other rights are granted to the U.S. Government.

このソフトウェアもしくはハードウェアは様々な情報管理アプリケーションでの一般的な使用のために開発されたものです。このソフトウェアもしくはハードウェアは、危険が伴うアプリケーション(人的傷害を発生させる可能性があるアプリケーションを含む)への用途を目的として開発されていません。このソフトウェアもしくはハードウェアを危険が伴うアプリケーションで使用する際、安全に使用するために、適切な安全装置、バックアップ、冗長性(redundancy)、その他の対策を講じることは使用者の責任となります。このソフトウェアもしくはハードウェアを危険が伴うアプリケーションで使用したことに起因して損害が発生しても、オラクル社およびその関連会社は一切の責任を負いかねます。

OracleおよびJavaはOracle Corporationおよびその関連企業の登録商標です。その他の名称は、それぞれの所有者の商標または登録商標です。

Intel、Intel Xeonは、Intel Corporationの商標または登録商標です。すべてのSPARCの商標はライセンスをもとに使用し、SPARC International, Inc.の商標または登録商標です。AMD、Opteron、AMDロゴ、AMD Opteronロゴは、Advanced Micro Devices, Inc.の商標または登録商標です。UNIXは、The Open Groupの登録商標です。

このソフトウェアまたはハードウェア、そしてドキュメントは、第三者のコンテンツ、製品、サービスへのアクセス、あるいはそれらに関する情報を提供することがあります。適用されるお客様とOracle Corporationとの間の契約に別段の定めがある場合を除いて、Oracle Corporationおよびその関連会社は、第三者のコンテンツ、製品、サービスに関して一切の責任を負わず、いかなる保証もいたしません。適用されるお客様とOracle Corporationとの間の契約に定めがある場合を除いて、Oracle Corporationおよびその関連会社は、第三者のコンテンツ、製品、サービスへのアクセスまたは使用によって損失、費用、あるいは損害が発生しても一切の責任を負いかねます。

目次

タイトルおよび著作権情報

はじめに

- 対象読者

- ドキュメントのアクセシビリティについて

- 関連ドキュメント

- 表記規則

『Oracle Streams拡張例』のこのリリースでの変更点

- Oracle Database 12cリリース1 (12.1)での変更点

1 簡単な単一ソース・レプリケーションの例

- 簡単な単一ソース・レプリケーションの例の概要

- 前提条件

- キューおよびデータベース・リンクの作成

- 1つの表に対する変更の取得、伝播および適用の構成

- hr.jobs表に対する変更および結果の表示

2 単一ソースの異機種間レプリケーションの例

- 単一ソースの異機種間レプリケーションの例の概要

- 前提条件

- キューおよびデータベース・リンクの作成

- 1つのデータベースからのデータを共有するスクリプトの例

- 1つのデータベースからのデータを共有する簡単な構成

- 1つのデータベースからのデータを共有する柔軟な構成

- hrスキーマ内の表に対するDML変更およびDDL変更

- 既存のOracle Streamsレプリケーション環境へのオブジェクトの追加

- hr.employees表に対するDML変更

- 既存のOracle Streamsレプリケーション環境へのデータベースの追加

- hr.departments表に対するDML変更

3 n-wayレプリケーションの例

- n-wayレプリケーション例の概要

- 前提条件

- mult1.example.comデータベースでのhrmultスキーマの作成

- キューおよびデータベース・リンクの作成

- n-wayレプリケーションを構成するスクリプトの例

- hrmultスキーマ内の表に対するDML変更およびDDL変更

4 単一データベースの取得および適用の例

- 単一データベースの取得および適用の例の概要

- 前提条件

- 環境の設定

- 取得および適用の構成

- DML変更の実行、結果の問合せ、およびメッセージのデキュー

5 LOBを含む論理変更レコードの例

- LOBを含むLCRを構成およびエンキューするスクリプトの例

6 ルールベースのアプリケーションの例

- ルールベースのアプリケーションの概要

- 明示的変数に格納された表以外のデータに対するルールの使用

- 繰返しの結果を持つ明示的変数内のデータに対するルールの使用

- 明示的変数内のデータに対するルールの部分評価の使用

- 表に格納されたデータに対するルールの使用

- 明示的変数と表データの両方に対するルールの使用

- 暗黙的変数および表データに対するルールの使用

- イベント・コンテキストおよび暗黙的変数のルールとの併用

- 問題のディスパッチおよび表の例の結果のチェック

索引

はじめに

このマニュアルでは、Oracle Streamsの機能を使用する詳細な例について説明します。

ここでは、次の項目について説明します。

- 対象読者

- ドキュメントのアクセシビリティについて

- 関連ドキュメント

- 表記規則

対象読者

『Oracle Streams拡張例』は、Oracle Streams環境の作成とメンテナンスを行うデータベース管理者を対象としています。これらの管理者は、次の1つ以上のタスクを実行します。

- Oracle Streams環境のプラン作成

- Oracle Streams環境の構成

- Oracle Streams環境の管理

- Oracle Streams環境の監視

このマニュアルを使用するには、リレーショナル・データベースの概念、SQL、分散データベースの管理、Oracle Streamsの一般的な概念、アドバンスト・キューイングの概念、PL/SQLおよびOracle Streams環境を稼働させるオペレーティング・システムに関する十分な知識が必要です。

ドキュメントのアクセシビリティについて

Oracleのアクセシビリティについての詳細情報は、Oracle Accessibility ProgramのWebサイト(http://www.oracle.com/pls/topic/lookup?ctx=acc&id=docacc)を参照してください。

Oracle Supportへのアクセス

サポートを購入したオラクル社のお客様は、My Oracle Supportを介して電子的なサポートにアクセスできます。詳細情報は(http://www.oracle.com/pls/topic/lookup?ctx=acc&id=info)か、聴覚に障害のあるお客様は(http://www.oracle.com/pls/topic/lookup?ctx=acc&id=trs)を参照してください。

関連ドキュメント

詳細は、次のOracleドキュメントを参照してください。

- 『Oracle Streams概要および管理』

- 『Oracle Streamsレプリケーション管理者ガイド』

- 『Oracle Database概要』

- 『Oracle Database管理者ガイド』

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

- 『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』

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

- 『Oracle Databaseユーティリティ』

- 『Oracle Database Heterogeneous Connectivityユーザーズ・ガイド』

- Oracle Enterprise Manager Cloud ControlのOracle Streamsツールに関するOracle Streamsオンライン・ヘルプ

このマニュアルに記載されている多数の例は、Oracle Databaseとともにデフォルトでインストールされる、サンプル・データベースのサンプル・スキーマを使用しています。これらのスキーマがどのように作成されているかと、その使用方法については、『Oracle Databaseサンプル・スキーマ』を参照してください。

表記規則

このマニュアルでは次の表記規則を使用します。

規則

意味

太字

太字は、操作に関連するGraphical User Interface要素、または本文中で定義されている用語および用語集に記載されている用語を示します。

イタリック体

イタリックは、ドキュメントのタイトル、強調またはユーザーが特定の値を指定するプレースホルダ変数を示します。

固定幅フォント

固定幅フォントは、段落内のコマンド、URL、サンプル内のコード、画面に表示されるテキスト、または入力するテキストを示します。

『Oracle Streams拡張例』のこのリリースでの変更点

この章の内容は次のとおりです。

- Oracle Database 12cリリース1 (12.1)での変更点

Oracle Database 12cリリース1 (12.1)での変更点

次に、Oracle Database 12c リリース1 (12.1)用の『Oracle Streams拡張例』での変更点を示します。

非推奨となった機能

- Oracle Streamsは、Oracle Database 12c リリース1 (12.1)で非推奨となっています。Oracle GoldenGateを使用して、Oracle Streamsのすべてのレプリケーション機能を置き換えます。

注意:
Oracle Database Advanced QueuingはOracle Streamsからは独立しており、継続して拡張されます。

関連項目:
Oracle GoldenGateのドキュメント

1 簡単な単一ソース・レプリケーションの例

この章では、Oracle Streamsを使用して構成できる簡単な単一ソース・レプリケーション環境の例を説明します。

この章の内容は次のとおりです。

- 簡単な単一ソース・レプリケーションの例の概要

- 前提条件

- キューおよびデータベース・リンクの作成

- 1つの表に対する変更の取得、伝播および適用の構成

- hr.jobs表に対する変更および結果の表示

簡単な単一ソース・レプリケーションの例の概要

この章の例では、Oracle Streamsを使用して2つのデータベース間の1つの表でデータをレプリケートする方法を示します。取得プロセスによって、str1.example.com Oracle Databaseでhrスキーマ内のjobs表に対して行われたデータ操作言語(DML)変更およびデータ定義言語(DDL)変更が取得され、これらの変更が伝播によってstr2.example.com Oracle Databaseへ伝播されます。次に、適用プロセスによってこれらの変更がstr2.example.comデータベースで適用されます。この例では、hr.jobs表がstr2.example.comデータベースで読取り専用であることを想定しています。

図1-1に、この環境の概要を示します。

図1-1 単一ソース・データベースからのデータを共有する簡単な例

前提条件

この章の例を開始する前に、前提条件となる次の作業を完了する必要があります。

- 次の初期化パラメータを指定の値に設定します。

- GLOBAL_NAMES: Oracle Streams環境の各データベースで、このパラメータをTRUEに設定する必要があります。

- COMPATIBLE: Oracle Streams環境の各データベースで、このパラメータを10.2.0以上に設定する必要があります。

- STREAMS_POOL_SIZE: オプションで、このパラメータを環境内の各データベースの適切な値に設定します。このパラメータでは、Oracle Streamsプールのサイズを指定します。Oracle Streamsプールは、バッファ・キューにメッセージを格納し、パラレル取得およびパラレル適用中の内部通信に使用されます。MEMORY_TARGET、MEMORY_MAX_TARGETまたはSGA_TARGET初期化パラメータを0 (ゼロ)以外の値に設定した場合、Oracle Streamsプールのサイズは自動的に管理されます。

関連項目:
Oracle Streams環境で重要なその他の初期化パラメータについては、『Oracle Streamsレプリケーション管理者ガイド』を参照してください。

- 取得される変更を生成するデータベースは、ARCHIVELOGモードで実行している必要があります。この例では、str1.example.comで変更が生成されるため、str1.example.comはARCHIVELOGモードで実行する必要があります。

関連項目:
ARCHIVELOGモードでデータベースを実行する方法の詳細は、『Oracle Database管理者ガイド』を参照してください。

- ネットワークとOracle Netを、str1.example.comデータベースがstr2.example.comデータベースと通信できるように構成します。

関連項目:
『Oracle Database Net Services管理者ガイド』

- レプリケーション環境の各データベースでOracle Streams管理者を作成します。この例では、データベースstr1.example.comおよびstr2.example.comで作成します。この例では、Oracle Streams管理者のユーザー名がstrmadminであると想定しています。

関連項目:
Oracle Streams管理者を作成する方法は、『Oracle Streamsレプリケーション管理者ガイド』を参照してください。

キューおよびデータベース・リンクの作成

次の手順を実行して、2つのOracle Databaseを含むOracle Streamsレプリケーション環境にキューおよびデータベース・リンクを作成します。

1. 出力およびスプール結果の表示

2. str1.example.comでのANYDATAキューの作成

3. str1.example.comでのデータベース・リンクの作成

4. str2.example.comでのANYDATAキューの設定

5. スプール結果のチェック

注意:
このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。

/************************* BEGINNING OF SCRIPT ******************************

手順1: 出力およびスプール結果の表示

SET ECHO ONを実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。

*/

SET ECHO ON
SPOOL streams_setup_simple.out

/*

手順2: str1.example.comでのANYDATAキューの作成

変更を取得するデータベースにOracle Streams管理者として接続します。この例では、データベースstr1.example.comに接続します。

*/

CONNECT strmadmin@str1.example.com

/*

SET_UP_QUEUEプロシージャを実行して、str1.example.comでstreams_queueというキューを作成します。このキューはANYDATAキューとして動作し、他のデータベースに伝播される取得された変更を保持します。

SET_UP_QUEUEプロシージャを実行すると、次のアクションが実行されます。

- streams_queue_tableというキュー表の作成。このキュー表は、Oracle Streams管理者(strmadmin)が所有し、このユーザーのデフォルトの記憶域を使用します。

- Oracle Streams管理者(strmadmin)が所有するstreams_queueというキューの作成。

- キューの起動。

*/

EXEC DBMS_STREAMS_ADM.SET_UP_QUEUE();

/*

手順3: str1.example.comでのデータベース・リンクの作成

変更が取得されるデータベースから変更が伝播されるデータベースにデータベース・リンクを作成します。この例では、変更が取得されるデータベースはstr1.example.comで、これらの変更はstr2.example.comに伝播されます。

*/

ACCEPT password PROMPT 'Enter password for user: ' HIDE

CREATE DATABASE LINK str2.example.com CONNECT TO strmadmin
IDENTIFIED BY &password USING 'str2.example.com';

/*

手順4: str2.example.comでのANYDATAキューの設定

Oracle Streams管理者としてstr2.example.comに接続します。

*/

CONNECT strmadmin@str2.example.com

/*

SET_UP_QUEUEプロシージャを実行して、str2.example.comでstreams_queueというキューを作成します。このキューはANYDATAキューとして動作し、このデータベースに適用される変更を保持します。

SET_UP_QUEUEプロシージャを実行すると、次のアクションが実行されます。

- streams_queue_tableというキュー表の作成。このキュー表は、Oracle Streams管理者(strmadmin)が所有し、このユーザーのデフォルトの記憶域を使用します。

- Oracle Streams管理者(strmadmin)が所有するstreams_queueというキューの作成。

- キューの起動。

*/

EXEC  DBMS_STREAMS_ADM.SET_UP_QUEUE();

/*

手順5: スプール結果のチェック

streams_setup_simple.outスプール・ファイルをチェックして、このスクリプトの完了後にすべてのアクションが正常に終了していることを確認します。

*/

SET ECHO OFF
SPOOL OFF

/*************************** END OF SCRIPT ******************************/

1つの表に対する変更の取得、伝播および適用の構成

次の手順を実行して、DBMS_STEAMS_ADMパッケージを使用したhr.jobs表の取得、伝播および適用の定義を指定します。

1. 出力およびスプール結果の表示

2. str1.example.comでの伝播の構成

3. str1.example.comでの取得プロセスの構成

4. str2.example.comでのhr.jobs表に対するインスタンス化SCNの設定

5. str2.example.comでの適用プロセスの構成

6. str2.example.comでの適用プロセスの起動

7. str1.example.comでの取得プロセスの起動

8. スプール結果のチェック

注意:
このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。

/************************* BEGINNING OF SCRIPT ******************************

手順1: 出力およびスプール結果の表示

SET ECHO ONを実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。

*/

SET ECHO ON
SPOOL streams_share_jobs.out

/*

手順2: str1.example.comでの伝播の構成

strmadminユーザーとしてstr1.example.comに接続します。

*/

CONNECT strmadmin@str1.example.com

/*

str1.example.comのキューからstr2.example.comのキューへのhr.jobs表に対するDML変更およびDDL変更の伝播を構成およびスケジュールします。

*/

BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_PROPAGATION_RULES(
table_name              => 'hr.jobs',
streams_name            => 'str1_to_str2',
source_queue_name       => 'strmadmin.streams_queue',
destination_queue_name  => 'strmadmin.streams_queue@str2.example.com',
include_dml             => TRUE,
include_ddl             => TRUE,
source_database         => 'str1.example.com',
inclusion_rule          => TRUE,
queue_to_queue          => TRUE);
END;
/

/*

手順3: str1.example.comでの取得プロセスの構成

str1.example.comでhr.jobs表に対する変更を取得するように取得プロセスを構成します。この手順では、この表に対する変更が取得プロセスによって取得され、指定したキューにエンキューされるように指定します。

また、この手順では、hr.jobs表をインスタンス化のために準備し、この表のすべての主キー列、一意キー列、ビットマップ索引列および外部キー列のサプリメンタル・ロギングを有効にします。サプリメンタル・ロギングによって、表に対する変更の追加の情報がREDOログに記録されます。適用プロセスでは、一意の行の識別や競合解消など、一部の操作を実行するために、この追加情報が必要です。この環境では、str1.example.comでのみ変更が取得されるため、hr.jobs表に対してサプリメンタル・ロギングを有効化する必要があるのはこのデータベースのみです。

関連項目:
『Oracle Streamsレプリケーション管理者ガイド』

*/

BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name     => 'hr.jobs',
streams_type   => 'capture',
streams_name   => 'capture_simp',
queue_name     => 'strmadmin.streams_queue',
include_dml    => TRUE,
include_ddl    => TRUE,
inclusion_rule => TRUE);
END;
/

/*

手順4: str2.example.comでのhr.jobs表に対するインスタンス化SCNの設定

この例では、hr.jobs表がstr1.example.comデータベースとstr2.example.comデータベースの両方に存在し、この表がこれらのデータベースで同期化されると想定しています。hr.jobs表はstr2.example.comにすでに存在するため、この例ではstr1.example.comでDBMS_FLASHBACKパッケージのGET_SYSTEM_CHANGE_NUMBERファンクションを使用して、ソース・データベースの現行のSCNを取得します。このSCNは、str2.example.comでDBMS_APPLY_ADMパッケージのSET_TABLE_INSTANTIATION_SCNプロシージャを実行するために使用されます。このプロシージャを実行して、str2.example.comのhr.jobs表にインスタンス化SCNを設定します。

SET_TABLE_INSTANTIATION_SCNプロシージャを使用すると、適用プロセスで無視される表のLCRと、適用プロセスで適用される表のLCRを制御できます。ソース・データベースからの表に関するLCRのコミットSCNが、接続先データベースでその表のインスタンス化SCN以下であれば、接続先データベースの適用プロセスではLCRが廃棄されます。それ以外の場合は、適用プロセスによってLCRが適用されます。

この例では、str2.example.comの適用プロセスはいずれも、この手順で取得したSCNの後にコミットされたSCNを持つhr.jobs表にトランザクションを適用します。

注意:
この例では、str1.example.comとstr2.example.comのhr.jobs表の内容は、この手順の実行時に一貫性があると想定しています。インスタンス化SCNの設定中に、この表でのアクティビティがないことを確認します。一貫性を確保するために、この手順の実行中に各データベースの表をロックすることをお薦めします。接続先データベースに表が存在しない場合は、エクスポート/インポートを使用してインスタンス化できます。

*/

DECLARE
iscn  NUMBER;         -- Variable to hold instantiation SCN value
BEGIN
iscn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER();
DBMS_APPLY_ADM.SET_TABLE_INSTANTIATION_SCN@STR2.EXAMPLE.COM(
source_object_name    => 'hr.jobs',
source_database_name  => 'str1.example.com',
instantiation_scn     => iscn);
END;
/

/*

手順5: str2.example.comでの適用プロセスの構成

strmadminユーザーとしてstr2.example.comに接続します。

*/

CONNECT strmadmin@str2.example.com

/*

hr.jobs表に変更を適用するようにstr2.example.comを構成します。

*/

BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name      => 'hr.jobs',
streams_type    => 'apply',
streams_name    => 'apply_simp',
queue_name      => 'strmadmin.streams_queue',
include_dml     => TRUE,
include_ddl     => TRUE,
source_database => 'str1.example.com',
inclusion_rule  => TRUE);
END;
/

/*

手順6: str2.example.comでの適用プロセスの起動

エラーが発生した場合に適用プロセスが無効化されないように、disable_on_errorパラメータをnに設定して、str2.example.comで適用プロセスを起動します。

*/

BEGIN
DBMS_APPLY_ADM.SET_PARAMETER(
apply_name  => 'apply_simp',
parameter   => 'disable_on_error',
value       => 'N');
END;
/

BEGIN
DBMS_APPLY_ADM.START_APPLY(
apply_name  => 'apply_simp');
END;
/

/*

手順7: str1.example.comでの取得プロセスの起動

strmadminユーザーとしてstr1.example.comに接続します。

*/

CONNECT strmadmin@str1.example.com

/*

str1.example.comで取得プロセスを起動します。

*/

BEGIN
DBMS_CAPTURE_ADM.START_CAPTURE(
capture_name  => 'capture_simp');
END;
/

/*

手順8: スプール結果のチェック

streams_share_jobs.outスプール・ファイルをチェックして、このスクリプトの完了後にすべてのアクションが正常に終了していることを確認します。

*/

SET ECHO OFF
SPOOL OFF

/*************************** END OF SCRIPT ******************************/

hr.jobs表に対する変更および結果の表示

次の手順を実行して、str1.example.comのhr.jobs表にDML変更およびDDL変更を行い、str1.example.comでそれらの変更が取得され、str1.example.comからstr2.example.comに伝播され、str2.example.comのhr.jobs表に適用されることを確認します。

手順1: str1.example.comのhr.jobsの変更

hr.jobs表に次の変更を行います。

CONNECT hr@str1.example.com
Enter password: password

UPDATE hr.jobs SET max_salary=9545 WHERE job_id='PR_REP';
COMMIT;

ALTER TABLE hr.jobs ADD(duties VARCHAR2(4000));

手順2: str2.example.comでのhr.jobs表の問合せおよび定義の表示

前述の手順で行った変更が取得、伝播および適用されてから、次の問合せを実行して、UPDATE変更が伝播されstr2.example.comで適用されていることを確認します。

CONNECT hr@str2.example.com
Enter password: password

SELECT * FROM hr.jobs WHERE job_id='PR_REP';

max_salary列の値が9545であるはずです。

次に、hr.jobs表の定義を表示して、ALTER TABLE変更が伝播されstr2.example.comで適用されていることを確認します。

DESC hr.jobs

duties列が最終列であるはずです。

2 単一ソースの異機種間レプリケーションの例

この章では、Oracle Streamsを使用して構成できる単一ソースの異機種間レプリケーション環境、およびこの環境に新しいオブジェクトおよびデータベースを追加する場合に必要となるタスクの例を説明します。

この章の内容は次のとおりです。

- 単一ソースの異機種間レプリケーションの例の概要

- 前提条件

- キューおよびデータベース・リンクの作成

- 1つのデータベースからのデータを共有するスクリプトの例

- hrスキーマ内の表に対するDML変更およびDDL変更

- 既存のOracle Streamsレプリケーション環境へのオブジェクトの追加

- hr.employees表に対するDML変更

- 既存のOracle Streamsレプリケーション環境へのデータベースの追加

- hr.departments表に対するDML変更

単一ソースの異機種間レプリケーションの例の概要

この例では、Oracle Streamsを使用して4つのデータベース間でデータをレプリケートする方法を説明します。データベースのうち3つがOracle Databaseで1つがSybaseデータベースであるため、異機種間環境です。dbs1.example.com Oracle Databaseで、hrスキーマ内の表に対して行われたDML変更とDDL変更が取得され、他の2つのOracle Databaseに伝播します。適用プロセスではOracle以外のデータベースにはDDL変更を適用できないため、DML変更のみが取得されてdbs4.example.comデータベースに伝播します。hrスキーマに対する変更は、dbs1.example.comでのみ発生します。hrスキーマは、環境内の他のデータベースでは読取り専用です。

図2-1に、この環境の概要を示します。

図2-1 単一ソース・データベースからのデータを共有する環境の例

図2-1に示すように、dbs1.example.comのhrスキーマには次の表が含まれています。

- countries

- departments

- employees

- job_history

- jobs

- locations

- リージョン

この例では、有向ネットワークを使用します(ソース・データベースで取得された変更は、1つ以上の中間データベースを介して、別のデータベースに伝播されることを意味します)。ここでは、dbs1.example.comデータベースがdbs3.example.comデータベースに、中間データベースdbs2.example.comを介して変更を伝播します。この構成は、有向ネットワークで前進するキューの一例です。また、dbs1.example.comデータベースは変更をdbs2.example.comデータベースに伝播し、このデータベースは、Oracle Database Gatewayを介して変更を直接dbs4.example.comデータベースに適用します。

この環境内の一部のデータベースには、特定の表がありません。データベースが表の中間データベースではなく、その表が含まれていない場合、そのデータベースには表に対する変更を伝播する必要はありません。たとえば、departments、employees、job_historyおよびjobsの各表は、dbs3.example.comには存在しません。したがって、これらの表に対する変更はdbs2.example.comからdbs3.example.comには伝播しません。

この例では、Oracle Streamsを使用して次の一連のアクションが実行されます。

1. 取得プロセスは、dbs1.example.comデータベースでhrスキーマ内のすべての表に対するDML変更とDDL変更を取得し、その変更をエンキューします。この例では、7つの表のうち4つに対する変更のみが接続先データベースに伝播されますが、「既存のOracle Streamsレプリケーション環境へのオブジェクトの追加」を示す例では、hrスキーマ内の残りの表が接続先データベースに追加されます。

2. dbs1.example.comデータベースから、これらの変更がメッセージの形式でdbs2.example.comのキューに伝播します。

3. dbs2.example.comで、jobs表に対するDML変更がassignments表(jobsの直接のマッピング)に対するDML変更に変換されてから適用されます。hrスキーマ内の他の表に対する変更は、dbs2.example.comでは適用されません。

4. dbs3.example.comのキューは、dbs1.example.comのcountries、locationsおよびregions表で発生した変更をdbs2.example.comのキューから受信するため、これらの変更はdbs2.example.comからdbs3.example.comに伝播します。この構成は、有向ネットワークの一例です。

5. dbs3.example.comの適用プロセスは、countries、locationsおよびregionsの各表に変更を適用します。

6. dbs4.example.comはSybaseデータベースであり、dbs1.example.comで発生したjobs表に対する変更をdbs2.example.comのキューから受信するため、これらの変更はOracle Database Gateway経由でdbs4.example.comのデータベース・リンクを使用してdbs2.example.comからリモートで適用されます。この構成は、異機種間サポートの一例です。

前提条件

この章の例を開始する前に、前提条件となる次の作業を完了する必要があります。

- 環境内のすべてのデータベースについて、次の初期化パラメータを指定の値に設定します。

- GLOBAL_NAMES: Oracle Streams環境の各データベースで、このパラメータをTRUEに設定する必要があります。

- COMPATIBLE: このパラメータは10.2.0以上に設定する必要があります。

- STREAMS_POOL_SIZE: オプションで、このパラメータを環境内の各データベースの適切な値に設定します。このパラメータでは、Oracle Streamsプールのサイズを指定します。Oracle Streamsプールは、バッファ・キューにメッセージを格納し、パラレル取得およびパラレル適用中の内部通信に使用されます。MEMORY_TARGET、MEMORY_MAX_TARGETまたはSGA_TARGET初期化パラメータを0 (ゼロ)以外の値に設定した場合、Oracle Streamsプールのサイズは自動的に管理されます。

関連項目:
Oracle Streams環境で重要なその他の初期化パラメータについては、『Oracle Streamsレプリケーション管理者ガイド』を参照してください。

- 取得される変更を生成するデータベースは、ARCHIVELOGモードで実行している必要があります。この例では、dbs1.example.comで変更が生成されるため、dbs1.example.comはARCHIVELOGモードで実行する必要があります。

関連項目:
ARCHIVELOGモードでデータベースを実行する方法の詳細は、『Oracle Database管理者ガイド』を参照してください。

- dbs2.example.com上のOracle Database Gatewayを、Sybaseデータベースdbs4.example.comと通信するように構成します。

関連項目:
『Oracle Database Heterogeneous Connectivityユーザーズ・ガイド』

- Sybaseデータベースdbs4.example.comでhrユーザーを設定します。

関連項目:
Sybaseデータベース内でユーザーと表を作成する方法については、Sybaseマニュアルを参照してください。

- dbs4.example.com Sybaseデータベースで、dbs1.example.com Oracle Databaseからhr.jobs表をインスタンス化します。

関連項目:
『Oracle Streamsレプリケーション管理者ガイド』

- ネットワークとOracle Netを、次のデータベースが相互に通信できるように構成します。

- dbs1.example.comとdbs2.example.com

- dbs2.example.comとdbs3.example.com

- dbs2.example.comとdbs4.example.com

- dbs3.example.comとdbs1.example.com(オプションのデータ・ポンプ・ネットワークのインスタンス化のため)

関連項目:
『Oracle Database Net Services管理者ガイド』

- レプリケーション環境の各Oracle DatabaseでOracle Streams管理者を作成します。この例では、データベースdbs1.example.com、dbs2.example.comおよびdbs3.example.comで作成します。この例では、Oracle Streams管理者のユーザー名がstrmadminであると想定しています。

関連項目:
Oracle Streams管理者を作成する方法は、『Oracle Streamsレプリケーション管理者ガイド』を参照してください。

キューおよびデータベース・リンクの作成

次の手順を実行して、3つのOracle Databaseと1つのSybaseデータベースを含むOracle Streamsレプリケーション環境にキューおよびデータベース・リンクを作成します。

1. 出力およびスプール結果の表示

2. dbs1.example.comでのANYDATAキューの作成

3. dbs1.example.comでのデータベース・リンクの作成

4. dbs2.example.comでのANYDATAキューの作成

5. dbs2.example.comでのデータベース・リンクの作成

6. dbs2.example.comでのhr.assignments表の作成

7. dbs3.example.comでのANYDATAキューの作成

8. dbs2.example.comでのデータベース・リンクの作成

9. dbs3.example.comでのhrスキーマ内のすべての表の削除

10. スプール結果のチェック

注意:
このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。

/************************* BEGINNING OF SCRIPT ******************************

手順1: 出力およびスプール結果の表示

SET ECHO ONを実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。

*/

SET ECHO ON
SPOOL streams_setup_single.out

/*

手順2: dbs1.example.comでのANYDATAキューの作成

変更を取得するデータベースにOracle Streams管理者として接続します。この例では、データベースdbs1.example.comに接続します。

*/

CONNECT strmadmin@dbs1.example.com

/*

SET_UP_QUEUEプロシージャを実行して、dbs1.example.comでstreams_queueというキューを作成します。このキューはANYDATAキューとして動作し、他のデータベースに伝播される取得された変更を保持します。

SET_UP_QUEUEプロシージャを実行すると、次のアクションが実行されます。

- streams_queue_tableというキュー表の作成。このキュー表は、Oracle Streams管理者(strmadmin)が所有し、このユーザーのデフォルトの記憶域を使用します。

- Oracle Streams管理者(strmadmin)が所有するstreams_queueというキューの作成。

- キューの起動。

*/

EXEC DBMS_STREAMS_ADM.SET_UP_QUEUE();

/*

手順3: dbs1.example.comでのデータベース・リンクの作成

変更が取得されるデータベースから変更が伝播されるデータベースにデータベース・リンクを作成します。この例では、変更が取得されるデータベースはdbs1.example.comで、これらの変更はdbs2.example.comに伝播されます。

*/

ACCEPT password PROMPT 'Enter password for user: ' HIDE

CREATE DATABASE LINK dbs2.example.com CONNECT TO strmadmin
IDENTIFIED BY &password USING 'dbs2.example.com';

/*

手順4: dbs2.example.comでのANYDATAキューの作成

Oracle Streams管理者としてdbs2.example.comに接続します。

*/

CONNECT strmadmin@dbs2.example.com

/*

SET_UP_QUEUEプロシージャを実行して、dbs2.example.comでstreams_queueというキューを作成します。このキューはANYDATAキューとして動作し、このデータベースに適用される変更および他のデータベースに伝播される変更を保持します。

SET_UP_QUEUEプロシージャを実行すると、次のアクションが実行されます。

- streams_queue_tableというキュー表の作成。このキュー表は、Oracle Streams管理者(strmadmin)が所有し、このユーザーのデフォルトの記憶域を使用します。

- Oracle Streams管理者(strmadmin)が所有するstreams_queueというキューの作成。

- キューの起動。

*/

EXEC  DBMS_STREAMS_ADM.SET_UP_QUEUE();

/*

手順5: dbs2.example.comでのデータベース・リンクの作成

変更が伝播されるデータベースへのデータベース・リンクを作成します。この例では、データベースdbs2.example.comからdbs3.example.com(別のOracle Database)およびdbs4.example.com(Sybaseデータベース)に変更が伝播されます。Sybaseデータベースへのデータベース・リンクが、Oracle Streams管理者ではなく表の所有者に接続されていることに注意してください。このデータベース・リンクは、そのデータベースのhr.jobs表を変更する権限を持つ、dbs4.example.comのいずれかのユーザーに接続できます。

注意:
Sybaseなどの一部のOracle以外のデータベースでは、ユーザー名およびパスワードの大/小文字が正しいことを確認する必要があります。したがって、Sybaseデータベースのユーザー名およびパスワードは、二重引用符で指定します。

*/

CREATE DATABASE LINK dbs3.example.com CONNECT TO strmadmin
IDENTIFIED BY &password USING 'dbs3.example.com';

CREATE DATABASE LINK dbs4.example.com CONNECT TO "hr"
IDENTIFIED BY "&password" USING 'dbs4.example.com';

/*

手順6: dbs2.example.comでのhr.assignments表の作成

この例では、dbs1.example.comのhr.jobs表に対する変更をdbs2.example.comのhr.assignments表に対する変更に変換するカスタム・ルールベースの変換について説明します。この例での変換を正常に実行するために、dbs2.example.comにhr.assignments表を作成する必要があります。

注意:
カスタム・ルールベースの変換を使用して表の名前を変更するかわりに、RENAME_TABLE宣言ルールベースの変換を使用できます。『Oracle Streams概要および管理』を参照してください。

hrとしてdbs2.example.comに接続します。

*/

CONNECT hr@dbs2.example.com

/*

dbs2.example.comデータベースにhr.assignments表を作成します。

*/

CREATE TABLE hr.assignments AS SELECT * FROM hr.jobs;

ALTER TABLE hr.assignments ADD PRIMARY KEY (job_id);

/*

手順7: dbs3.example.comでのANYDATAキューの作成

Oracle Streams管理者としてdbs3.example.comに接続します。

*/

CONNECT strmadmin@dbs3.example.com

/*

SET_UP_QUEUEプロシージャを実行して、dbs3.example.comでstreams_queueというキューを作成します。このキューはANYDATAキューとして動作し、このデータベースに適用される変更を保持します。

SET_UP_QUEUEプロシージャを実行すると、次のアクションが実行されます。

- streams_queue_tableというキュー表の作成。このキュー表は、Oracle Streams管理者(strmadmin)が所有し、このユーザーのデフォルトの記憶域を使用します。

- Oracle Streams管理者(strmadmin)が所有するstreams_queueというキューの作成。

- キューの起動。

*/

EXEC  DBMS_STREAMS_ADM.SET_UP_QUEUE();

/*

手順8: dbs3.example.comからdbs1.example.comへのデータベース・リンクの作成

dbs3.example.comからdbs1.example.comへのデータベース・リンクを作成します。このデータベース・リンクは、この例の後半で、手順9で削除するデータベース・オブジェクトの一部をインスタンス化するために使用します。この例では、DBMS_DATAPUMPパッケージを使用して、dbs1.example.comデータベースから直接これらのデータベース・オブジェクトのネットワーク・インポートを実行します。この例ではネットワーク・インポートを実行するため、ダンプ・ファイルは不要です。

または、ソース・データベースdbs1.example.comでエクスポートを実行し、エクスポート・ダンプ・ファイルを接続先データベースdbs3.example.comに転送して、接続先データベースでエクスポート・ダンプ・ファイルをインポートすることもできます。この場合、この手順で作成するデータベース・リンクは不要です。

*/

CREATE DATABASE LINK dbs1.example.com CONNECT TO strmadmin
IDENTIFIED BY &password USING 'dbs1.example.com';

/*

手順9: dbs3.example.comでのhrスキーマ内のすべての表の削除

この例では、データ・ポンプを使用してdbs1.example.comからdbs3.example.comに表をインポートすることによって、hrスキーマ内の表をインスタンス化する方法について説明します。この例でのインスタンス化を正常に実行するために、dbs3.example.comでこれらの表を削除する必要があります。

hrとしてdbs3.example.comに接続します。

*/

CONNECT hr@dbs3.example.com

/*

dbs3.example.comデータベースのhrスキーマ内のすべての表を削除します。

注意:
この手順を実行してhrスキーマ内のすべての表を削除した場合、この例の残りの項の手順を実行して、dbs3.example.comでhrスキーマを再インスタンス化する必要があります。hrスキーマがOracle Databaseに存在しない場合、Oracleマニュアル・セットの一部の例が失敗する可能性があります。

*/

DROP TABLE hr.countries CASCADE CONSTRAINTS;
DROP TABLE hr.departments CASCADE CONSTRAINTS;
DROP TABLE hr.employees CASCADE CONSTRAINTS;
DROP TABLE hr.job_history CASCADE CONSTRAINTS;
DROP TABLE hr.jobs CASCADE CONSTRAINTS;
DROP TABLE hr.locations CASCADE CONSTRAINTS;
DROP TABLE hr.regions CASCADE CONSTRAINTS;

/*

手順10: スプール結果のチェック

streams_setup_single.outスプール・ファイルをチェックして、このスクリプトの完了後にすべてのアクションが正常に終了していることを確認します。

*/

SET ECHO OFF
SPOOL OFF

/*************************** END OF SCRIPT ******************************/

1つのデータベースからのデータを共有するスクリプトの例

この例では、Oracle Streamsを使用してhrスキーマ内の表のレプリケーションを行う2つの方法について説明します。

- 「1つのデータベースからのデータを共有する簡単な構成」では、簡単な方法での環境の構成を示します。この例では、DBMS_STREAMS_ADMパッケージを使用して、取得プロセス、伝播および適用プロセスと、それらに関連付けられたルール・セットを作成します。DBMS_STREAMS_ADMパッケージを使用すると、最も簡単にOracle Streams環境を構成できます。

- 「1つのデータベースからのデータを共有する柔軟な構成」では、より柔軟な方法でのこの環境の構成を示します。この例では、DBMS_CAPTURE_ADMパッケージを使用して取得プロセスを作成し、DBMS_PROPAGATION_ADMパッケージを使用して伝播を作成し、DBMS_APPLY_ADMパッケージを使用して適用プロセスを作成します。また、この例では、DBMS_RULES_ADMパッケージを使用して、これらの取得プロセス、伝播および適用プロセスに関連付けられたルール・セットを作成および移入します。DBMS_STREAMS_ADMパッケージのかわりにこれらのパッケージを使用すると、より多くの構成オプションを使用でき、柔軟性が向上します。

注意:
これらの例では、同じOracle Streams環境を構成する2つの異なる方法を示します。したがって、特定の分散データベース・システムに、いずれかの例のみを実行する必要があります。両方の例を実行すると、オブジェクトがすでに存在することを示すエラーが発生します。

1つのデータベースからのデータを共有する簡単な構成

次の手順を実行して、主にDBMS_STEAMS_ADMパッケージを使用して、取得、伝播および適用の定義を指定します。

1. 出力およびスプール結果の表示

2. dbs1.example.comでの伝播の構成

3. dbs1.example.comでの取得プロセスの構成

4. 他のデータベースでの既存の表に対するインスタンス化SCNの設定

5. dbs3.example.comでのdbs1.example.comの表のインスタンス化

6. dbs3.example.comでの適用プロセスの構成

7. dbs3.example.comでの適用プロセスの適用ユーザーとしてのhrの指定

8. hrユーザーへの適用プロセスのルール・セットに対するEXECUTE権限の付与

9. dbs3.example.comでの適用プロセスの起動

10. dbs2.example.comでの伝播の構成

11. dbs2.example.comでの行LCRのカスタム・ルールベースの変換の作成

12. dbs2.example.comでのローカル適用を実行するための適用プロセスの構成

13. dbs2.example.comでの適用プロセスの適用ユーザーとしてのhrの指定

14. hrユーザーへの適用プロセスのルール・セットに対するEXECUTE権限の付与

15. dbs2.example.comでのローカル適用を実行するための適用プロセスの起動

16. dbs4.example.comでの適用を実行するためのdbs2.example.comでの適用プロセスの構成

17. dbs4.example.comでの適用を実行するためのdbs2.example.comでの適用プロセスの起動

18. dbs1.example.comでの取得プロセスの起動

19. スプール結果のチェック

注意:
このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。

/************************* BEGINNING OF SCRIPT ******************************

手順1: 出力およびスプール結果の表示

SET ECHO ONを実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。

*/

SET ECHO ON
SPOOL streams_share_schema1.out

/*

手順2: dbs1.example.comでの伝播の構成

strmadminユーザーとしてdbs1.example.comに接続します。

*/

CONNECT strmadmin@dbs1.example.com

/*

dbs1.example.comのキューからdbs2.example.comのキューへのhrスキーマ内のDML変更およびDDL変更の伝播を構成およびスケジュールします。

*/

BEGIN
DBMS_STREAMS_ADM.ADD_SCHEMA_PROPAGATION_RULES(
schema_name             => 'hr',
streams_name            => 'dbs1_to_dbs2',
source_queue_name       => 'strmadmin.streams_queue',
destination_queue_name  => 'strmadmin.streams_queue@dbs2.example.com',
include_dml             => TRUE,
include_ddl             => TRUE,
source_database         => 'dbs1.example.com',
inclusion_rule          => TRUE,
queue_to_queue          => TRUE);
END;
/

/*

手順3: dbs1.example.comでの取得プロセスの構成

dbs1.example.comでhrスキーマ全体に対する変更を取得するように取得プロセスを構成します。この手順では、指定したスキーマ内の表に対する変更が取得プロセスによって取得され、指定したキューにエンキューされるように指定します。

また、この手順では、hrスキーマをインスタンス化のために準備し、このスキーマ内の表のすべての主キー列、一意キー列、ビットマップ索引列および外部キー列のサプリメンタル・ロギングを有効にします。サプリメンタル・ロギングによって、表に対する変更の追加の情報がREDOログに記録されます。適用プロセスでは、一意の行の識別や競合解消など、一部の操作を実行するために、この追加情報が必要です。この環境では、dbs1.example.comデータベースでのみ変更が取得されるため、hrスキーマ内の表に対してサプリメンタル・ロギングを指定する必要があるのはこのデータベースのみです。

関連項目:
『Oracle Streamsレプリケーション管理者ガイド』

*/

BEGIN
DBMS_STREAMS_ADM.ADD_SCHEMA_RULES(
schema_name    => 'hr',
streams_type   => 'capture',
streams_name   => 'capture',
queue_name     => 'strmadmin.streams_queue',
include_dml    => TRUE,
include_ddl    => TRUE,
inclusion_rule => TRUE);
END;
/

/*

手順4: 他のデータベースでの既存の表に対するインスタンス化SCNの設定

この例では、dbs2.example.comおよびdbs4.example.comにhr.jobs表がすでに存在します。dbs2.example.comでは、この表の名前はassignmentsですが、この表はdbs1.example.comのjobs表と同じ形式で、同じデータを含んでいます。また、この例では、dbs4.example.comはSybaseデータベースです。Oracle Streams環境内の他のすべての表が、データ・ポンプ・インポートを使用して他の接続先データベースでインスタンス化されます。

hr.jobs表はdbs2.example.comおよびdbs4.example.comにすでに存在するため、この例ではdbs1.example.comでDBMS_FLASHBACKパッケージのGET_SYSTEM_CHANGE_NUMBERファンクションを使用して、データベースの現行のSCNを取得します。このSCNは、dbs2.example.comでDBMS_APPLY_ADMパッケージのSET_TABLE_INSTANTIATION_SCNプロシージャを実行するために使用されます。このプロシージャを2回実行して、dbs2.example.comおよびdbs4.example.comでhr.jobs表にインスタンス化SCNを設定します。

SET_TABLE_INSTANTIATION_SCNプロシージャを使用すると、適用プロセスで無視される表のLCRと、適用プロセスで適用される表のLCRを制御できます。ソース・データベースからの表に関するLCRのコミットSCNが、接続先データベースでその表のインスタンス化SCN以下であれば、接続先データベースの適用プロセスではLCRが廃棄されます。それ以外の場合は、適用プロセスによってLCRが適用されます。

この例では、dbs2.example.comの適用プロセスはいずれも、この手順で取得したSCNの後にコミットされたSCNを持つhr.jobs表にトランザクションを適用します。

注意:
この例では、dbs1.example.com、dbs2.example.com(hr.assignments)およびdbs4.example.comのhr.jobs表の内容は、この手順が完了した時点で一貫性があると想定しています。一貫性を確保するために、この手順の実行中に各データベースの表をロックすることをお薦めします。

*/

DECLARE
iscn  NUMBER;         -- Variable to hold instantiation SCN value
BEGIN
iscn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER();
DBMS_APPLY_ADM.SET_TABLE_INSTANTIATION_SCN@DBS2.EXAMPLE.COM(
source_object_name    => 'hr.jobs',
source_database_name  => 'dbs1.example.com',
instantiation_scn     => iscn);
DBMS_APPLY_ADM.SET_TABLE_INSTANTIATION_SCN@DBS2.EXAMPLE.COM(
source_object_name    => 'hr.jobs',
source_database_name  => 'dbs1.example.com',
instantiation_scn     => iscn,
apply_database_link   => 'dbs4.example.com');
END;
/

/*

手順5: dbs3.example.comでのdbs1.example.comの表のインスタンス化

この例では、データ・ポンプを使用して次の表のネットワーク・インポートを実行します。

- hr.countries

- hr.locations

- hr.regions

ネットワーク・インポートとは、エクスポート・ダンプ・ファイルを使用せずに、データ・ポンプでdbs1.example.comからこれらの表をインポートすることを意味します。

関連項目:
インポートを実行する方法の詳細は、『Oracle Databaseユーティリティ』を参照してください。

strmadminユーザーとしてdbs3.example.comに接続します。

*/

CONNECT strmadmin@dbs3.example.com

/*

この例では、DBMS_DATAPUMPパッケージを使用して表のインポートを実行します。簡略化するために、どのAPIコールからの例外も捕捉されません。ただし、例外ハンドラを定義し、障害発生時にGET_STATUSをコールしてエラーの詳細情報を取得することをお薦めします。インポートを監視する場合は、インポート・データベースでDBA_DATAPUMP_JOBSデータ・ディクショナリ・ビューを問い合せます。

*/

SET SERVEROUTPUT ON
DECLARE
h1        NUMBER;         -- Data Pump job handle
sscn      NUMBER;         -- Variable to hold current source SCN
job_state VARCHAR2(30);   -- To keep track of job state
js        ku$_JobStatus;  -- The job status from GET_STATUS
sts       ku$_Status;     -- The status object returned by GET_STATUS
job_not_exist    exception;
pragma exception_init(job_not_exist, -31626);
BEGIN
-- Create a (user-named) Data Pump job to do a table-level import.
h1 := DBMS_DATAPUMP.OPEN(
operation   => 'IMPORT',
job_mode    => 'TABLE',
remote_link => 'DBS1.EXAMPLE.COM',
job_name    => 'dp_sing1');
-- A metadata filter is used to specify the schema that owns the tables
-- that will be imported.
DBMS_DATAPUMP.METADATA_FILTER(
handle    => h1,
name      => 'SCHEMA_EXPR',
value     => '=''HR''');
-- A metadata filter is used to specify the tables that will be imported.
DBMS_DATAPUMP.METADATA_FILTER(
handle    => h1,
name      => 'NAME_EXPR',
value     => 'IN(''COUNTRIES'', ''REGIONS'', ''LOCATIONS'')');
-- Get the current SCN of the source database, and set the FLASHBACK_SCN
-- parameter to this value to ensure consistency between all of the
-- objects included in the import.
sscn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER@dbs1.example.com();
DBMS_DATAPUMP.SET_PARAMETER(
handle => h1,
name   => 'FLASHBACK_SCN',
value  => sscn);
-- Start the job.
DBMS_DATAPUMP.START_JOB(h1);
-- The import job should be running. In the following loop, the job
-- is monitored until it completes.
job_state := 'UNDEFINED';
BEGIN
WHILE (job_state != 'COMPLETED') AND (job_state != 'STOPPED') LOOP
sts:=DBMS_DATAPUMP.GET_STATUS(
handle  => h1,
mask    => DBMS_DATAPUMP.KU$_STATUS_JOB_ERROR +
DBMS_DATAPUMP.KU$_STATUS_JOB_STATUS +
DBMS_DATAPUMP.KU$_STATUS_WIP,
timeout => -1);
js := sts.job_status;
DBMS_LOCK.SLEEP(10);
job_state := js.state;
END LOOP;
-- Gets an exception when job no longer exists
EXCEPTION WHEN job_not_exist THEN
DBMS_OUTPUT.PUT_LINE('Data Pump job has completed');
DBMS_OUTPUT.PUT_LINE('Instantiation SCN: ' ||sscn);
END;
END;
/

/*

手順6: dbs3.example.comでの適用プロセスの構成

strmadminユーザーとしてdbs3.example.comに接続します。

*/

CONNECT strmadmin@dbs3.example.com

/*

countries表、locations表およびregions表に変更を適用するようにdbs3.example.comを構成します。

*/

BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name      => 'hr.countries',
streams_type    => 'apply',
streams_name    => 'apply',
queue_name      => 'strmadmin.streams_queue',
include_dml     => TRUE,
include_ddl     => TRUE,
source_database => 'dbs1.example.com',
inclusion_rule  => TRUE);
END;
/

BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name      => 'hr.locations',
streams_type    => 'apply',
streams_name    => 'apply',
queue_name      => 'strmadmin.streams_queue',
include_dml     => TRUE,
include_ddl     => TRUE,
source_database => 'dbs1.example.com',
inclusion_rule  => TRUE);
END;
/

BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name      => 'hr.regions',
streams_type    => 'apply',
streams_name    => 'apply',
queue_name      => 'strmadmin.streams_queue',
include_dml     => TRUE,
include_ddl     => TRUE,
source_database => 'dbs1.example.com',
inclusion_rule  => TRUE);
END;
/

/*

手順7: dbs3.example.comでの適用プロセスの適用ユーザーとしてのhrの指定

この例では、hrユーザーが、このデータベースで適用プロセスによって変更が適用されるすべてのデータベース・オブジェクトを所有します。したがって、hrはこれらのデータベース・オブジェクトを変更するために必要な権限をすでに持っており、hrを適用ユーザーにすることが有効です。

前述の手順で適用プロセスを作成したときに、適用プロセスを作成したプロシージャをOracle Streams管理者strmadminが実行したため、デフォルトでは、strmadminが適用ユーザーとして指定されています。hrを適用ユーザーとして指定するかわりに、strmadminを適用ユーザーのままにしておくこともできますが、この場合、変更が適用されるすべてのデータベース・オブジェクトに対する権限、および適用プロセスで使用されるすべてのユーザー・プロシージャを実行する権限をstrmadminに付与する必要があります。適用プロセスが複数のスキーマ内のデータベース・オブジェクトに変更を適用する環境では、Oracle Streams管理者を適用ユーザーとして使用する方が有効な場合があります。

関連項目:
Oracle Streams管理者を構成する方法の詳細は、『Oracle Streamsレプリケーション管理者ガイド』を参照してください。

*/

BEGIN
DBMS_APPLY_ADM.ALTER_APPLY(
apply_name => 'apply',
apply_user => 'hr');
END;
/

/*

手順8: hrユーザーへの適用プロセスのルール・セットに対するEXECUTE権限の付与

前述の手順でhrユーザーを適用ユーザーとして指定したため、hrユーザーには、適用プロセスで使用されるポジティブ・ルール・セットに対するEXECUTE権限が必要です

*/

DECLARE
rs_name  VARCHAR2(64);   -- Variable to hold rule set name
BEGIN
SELECT RULE_SET_OWNER||'.'||RULE_SET_NAME
INTO rs_name
FROM DBA_APPLY
WHERE APPLY_NAME='APPLY';
DBMS_RULE_ADM.GRANT_OBJECT_PRIVILEGE(
privilege   => SYS.DBMS_RULE_ADM.EXECUTE_ON_RULE_SET,
object_name => rs_name,
grantee     => 'hr');
END;
/

/*

手順9: dbs3.example.comでの適用プロセスの起動

エラーが発生した場合に適用プロセスが無効化されないように、disable_on_errorパラメータをnに設定して、dbs3.example.comで適用プロセスを起動します。

*/

BEGIN
DBMS_APPLY_ADM.SET_PARAMETER(
apply_name  => 'apply',
parameter   => 'disable_on_error',
value       => 'N');
END;
/

BEGIN
DBMS_APPLY_ADM.START_APPLY(
apply_name  => 'apply');
END;
/

/*

手順10: dbs2.example.comでの伝播の構成

strmadminユーザーとしてdbs2.example.comに接続します。

*/

CONNECT strmadmin@dbs2.example.com

/*

dbs2.example.comのキューからdbs3.example.comのキューへの伝播を構成およびスケジュールします。この伝播は、dbs3.example.comで変更を適用する表ごとに指定する必要があります。dbs2.example.comの変更はdbs1.example.comで発生したものであるため、この構成は、有向ネットワークの一例です。

*/

BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_PROPAGATION_RULES(
table_name               => 'hr.countries',
streams_name             => 'dbs2_to_dbs3',
source_queue_name        => 'strmadmin.streams_queue',
destination_queue_name   => 'strmadmin.streams_queue@dbs3.example.com',
include_dml              => TRUE,
include_ddl              => TRUE,
source_database          => 'dbs1.example.com',
inclusion_rule           => TRUE,
queue_to_queue           => TRUE);
END;
/

BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_PROPAGATION_RULES(
table_name              => 'hr.locations',
streams_name            => 'dbs2_to_dbs3',
source_queue_name       => 'strmadmin.streams_queue',
destination_queue_name  => 'strmadmin.streams_queue@dbs3.example.com',
include_dml             => TRUE,
include_ddl             => TRUE,
source_database         => 'dbs1.example.com',
inclusion_rule          => TRUE);
END;
/

BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_PROPAGATION_RULES(
table_name              => 'hr.regions',
streams_name            => 'dbs2_to_dbs3',
source_queue_name       => 'strmadmin.streams_queue',
destination_queue_name  => 'strmadmin.streams_queue@dbs3.example.com',
include_dml             => TRUE,
include_ddl             => TRUE,
source_database         => 'dbs1.example.com',
inclusion_rule          => TRUE);
END;
/

/*

手順11: dbs2.example.comでの行LCRのカスタム・ルールベースの変換の作成

hrユーザーとしてdbs2.example.comに接続します。

*/

CONNECT hr@dbs2.example.com

/*

dbs1.example.comのjobs表に対するDML文によって発生する行変更をdbs2.example.comのassignments表に対する行変更に変換するカスタム・ルールベースの変換ファンクションを作成します。

次のファンクションを実行すると、jobs表のすべての行LCRがassignments表の行LCRに変換されます。

注意:
assignments表にDDL変更も適用された場合、DDL LCR用に別の変換が必要になります。この変換では、オブジェクト名およびDDLテキストを変更する必要があります。

*/

CREATE OR REPLACE FUNCTION hr.to_assignments_trans_dml(
p_in_data in ANYDATA)
RETURN ANYDATA IS out_data SYS.LCR$_ROW_RECORD;
tc   pls_integer;
BEGIN
-- Typecast AnyData to LCR$_ROW_RECORD
tc := p_in_data.GetObject(out_data);
IF out_data.GET_OBJECT_NAME() = 'JOBS'
THEN
-- Transform the in_data into the out_data
out_data.SET_OBJECT_NAME('ASSIGNMENTS');
END IF;
-- Convert to AnyData
RETURN ANYDATA.ConvertObject(out_data);
END;
/

/*

手順12: dbs2.example.comでのローカル適用を実行するための適用プロセスの構成

strmadminユーザーとしてdbs2.example.comに接続します。

*/

CONNECT strmadmin@dbs2.example.com

/*

assignments表に変更を適用するようにdbs2.example.comを構成します。assignments表がdbs1.example.comのjobs表から変更を受信することに注意してください。

*/

DECLARE
to_assignments_rulename_dml   VARCHAR2(30);
dummy_rule                    VARCHAR2(30);
BEGIN
--  DML changes to the jobs table from dbs1.example.com are applied
--  to the assignments table. The to_assignments_rulename_dml variable
--  is an out parameter in this call.
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name      => 'hr.jobs', -- jobs, not assignments, specified
streams_type    => 'apply',
streams_name    => 'apply_dbs2',
queue_name      => 'strmadmin.streams_queue',
include_dml     => TRUE,
include_ddl     => FALSE,
source_database => 'dbs1.example.com',
dml_rule_name   => to_assignments_rulename_dml,
ddl_rule_name   => dummy_rule,
inclusion_rule  => TRUE);
--  Modify the rule for the hr.jobs table to use the transformation function.
DBMS_STREAMS_ADM.SET_RULE_TRANSFORM_FUNCTION(
rule_name          => to_assignments_rulename_dml,
transform_function => 'hr.to_assignments_trans_dml');
END;
/

/*

手順13: dbs2.example.comでの適用プロセスの適用ユーザーとしてのhrの指定

この例では、hrユーザーが、このデータベースで適用プロセスによって変更が適用されるすべてのデータベース・オブジェクトを所有します。したがって、hrはこれらのデータベース・オブジェクトを変更するために必要な権限をすでに持っており、hrを適用ユーザーにすることが有効です。

前述の手順で適用プロセスを作成したときに、適用プロセスを作成したプロシージャをOracle Streams管理者strmadminが実行したため、デフォルトでは、strmadminが適用ユーザーとして指定されています。hrを適用ユーザーとして指定するかわりに、strmadminを適用ユーザーのままにしておくこともできますが、この場合、変更が適用されるすべてのデータベース・オブジェクトに対する権限、および適用プロセスで使用されるすべてのユーザー・プロシージャを実行する権限をstrmadminに付与する必要があります。適用プロセスが複数のスキーマ内のデータベース・オブジェクトに変更を適用する環境では、Oracle Streams管理者を適用ユーザーとして使用する方が有効な場合があります。

関連項目:
Oracle Streams管理者を構成する方法の詳細は、『Oracle Streamsレプリケーション管理者ガイド』を参照してください。

*/

BEGIN
DBMS_APPLY_ADM.ALTER_APPLY(
apply_name => 'apply_dbs2',
apply_user => 'hr');
END;
/

/*

手順14: hrユーザーへの適用プロセスのルール・セットに対するEXECUTE権限の付与

前述の手順でhrユーザーを適用ユーザーとして指定したため、hrユーザーには、適用プロセスで使用されるポジティブ・ルール・セットに対するEXECUTE権限が必要です

*/

DECLARE
rs_name  VARCHAR2(64);   -- Variable to hold rule set name
BEGIN
SELECT RULE_SET_OWNER||'.'||RULE_SET_NAME
INTO rs_name
FROM DBA_APPLY
WHERE APPLY_NAME='APPLY_DBS2';
DBMS_RULE_ADM.GRANT_OBJECT_PRIVILEGE(
privilege   => SYS.DBMS_RULE_ADM.EXECUTE_ON_RULE_SET,
object_name => rs_name,
grantee     => 'hr');
END;
/

/*

手順15: dbs2.example.comでのローカル適用を実行するための適用プロセスの起動

エラーが発生した場合に適用プロセスが無効化されないように、disable_on_errorパラメータをnに設定して、dbs2.example.comでローカル適用を実行するために適用プロセスを起動します。

*/

BEGIN
DBMS_APPLY_ADM.SET_PARAMETER(
apply_name  => 'apply_dbs2',
parameter   => 'disable_on_error',
value       => 'N');
END;
/

BEGIN
DBMS_APPLY_ADM.START_APPLY(
apply_name  => 'apply_dbs2');
END;
/

/*

手順16: dbs4.example.comでの適用を実行するためのdbs2.example.comでの適用プロセスの構成

dbs4.example.com(Sybaseデータベース)の適用プロセスを構成します。dbs2.example.comデータベースは、dbs4.example.comへのゲートウェイとして機能しています。したがって、dbs4.example.comの適用プロセスは、dbs2.example.comで構成する必要があります。適用プロセスでDDL変更をOracle以外のデータベースに適用することはできません。したがって、ADD_TABLE_RULESプロシージャの実行時に、include_ddlパラメータがFALSEに設定されています。

*/

BEGIN
DBMS_APPLY_ADM.CREATE_APPLY(
queue_name          => 'strmadmin.streams_queue',
apply_name          => 'apply_dbs4',
apply_database_link => 'dbs4.example.com',
apply_captured      => TRUE);
END;
/

BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name      => 'hr.jobs',
streams_type    => 'apply',
streams_name    => 'apply_dbs4',
queue_name      => 'strmadmin.streams_queue',
include_dml     => TRUE,
include_ddl     => FALSE,
source_database => 'dbs1.example.com',
inclusion_rule  => TRUE);
END;
/

/*

手順17: dbs4.example.comでの適用を実行するためのdbs2.example.comでの適用プロセスの起動

エラーが発生した場合に適用プロセスが無効化されないように、disable_on_errorパラメータをnに設定して、データベース・リンクdbs4.example.comを使用してSybaseのリモート適用を開始します。

*/

BEGIN
DBMS_APPLY_ADM.SET_PARAMETER(
apply_name  => 'apply_dbs4',
parameter   => 'disable_on_error',
value       => 'N');
END;
/

BEGIN
DBMS_APPLY_ADM.START_APPLY(
apply_name  => 'apply_dbs4');
END;
/

/*

手順18: dbs1.example.comでの取得プロセスの起動

strmadminユーザーとしてdbs1.example.comに接続します。

*/

CONNECT strmadmin@dbs1.example.com

/*

dbs1.example.comで取得プロセスを起動します。

*/

BEGIN
DBMS_CAPTURE_ADM.START_CAPTURE(
capture_name  => 'capture');
END;
/

/*

手順19: スプール結果のチェック

streams_share_schema1.outスプール・ファイルをチェックして、このスクリプトの完了後にすべてのアクションが正常に終了していることを確認します。

*/

SET ECHO OFF
SPOOL OFF

/*

ここで、dbs1.example.comの特定の表に対してDML変更およびDDL変更を行い、この環境内のOracle Streamsプロセスおよび伝播について構成したルールに基づいて、環境内の他のデータベースにこれらの変更がレプリケートされていることを確認できます。

関連項目:
この環境内でレプリケートされる変更の例については、「hrスキーマ内の表に対するDML変更およびDDL変更」を参照してください。

/*************************** END OF SCRIPT ******************************/

1つのデータベースからのデータを共有する柔軟な構成

次の手順を実行して、より柔軟な方法を使用して、取得、伝播および適用の定義を指定します。この方法では、DBMS_STREAMS_ADMパッケージを使用しません。かわりに、次のパッケージを使用します。

- DBMS_CAPTURE_ADMパッケージ。取得プロセスを構成します。

- DBMS_PROPAGATION_ADMパッケージ。伝播を構成します。

- DBMS_APPLY_ADMパッケージ。適用プロセスを構成します。

- DBMS_RULES_ADMパッケージ。取得プロセス、伝播および適用プロセスのルールおよびルール・セットを指定します。

注意:
ALL_STREAMS_TABLE_RULESおよびDBA_STREAMS_TABLE_RULESデータ・ディクショナリ・ビューはいずれも、この例で作成するルールでは移入されません。この例で作成されるルールを表示するには、ALL_STREAMS_RULESまたはDBA_STREAMS_RULESデータ・ディクショナリ・ビューを問い合せます。

この例の手順は次のとおりです。

1. 出力およびスプール結果の表示

2. dbs1.example.comでの伝播の構成

3. dbs1.example.comでの取得プロセスの構成

4. dbs1.example.comでのhrスキーマのインスタンス化のための準備

5. 他のデータベースでの既存の表に対するインスタンス化SCNの設定

6. dbs3.example.comでのdbs1.example.comの表のインスタンス化

7. dbs3.example.comでの適用プロセスの構成

8. hrユーザーへの適用プロセスのルール・セットに対するEXECUTE権限の付与

9. dbs3.example.comでの適用プロセスの起動

10. dbs2.example.comでの伝播の構成

11. dbs2.example.comでの行LCRのカスタム・ルールベースの変換の作成

12. dbs2.example.comでのローカル適用を実行するための適用プロセスの構成

13. hrユーザーへの適用プロセスのルール・セットに対するEXECUTE権限の付与

14. dbs2.example.comでのローカル適用を実行するための適用プロセスの起動

15. dbs4.example.comでの適用を実行するためのdbs2.example.comでの適用プロセスの構成

16. dbs4.example.comでの適用を実行するためのdbs2.example.comでの適用プロセスの起動

17. dbs1.example.comでの取得プロセスの起動

18. スプール結果のチェック

注意:
このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。

/************************* BEGINNING OF SCRIPT ******************************

手順1: 出力およびスプール結果の表示

SET ECHO ONを実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。

*/

SET ECHO ON
SPOOL streams_share_schema2.out

/*

手順2: dbs1.example.comでの伝播の構成

strmadminユーザーとしてdbs1.example.comに接続します。

*/

CONNECT strmadmin@dbs1.example.com

/*

dbs1.example.comのキューからdbs2.example.comのキューへの伝播を構成およびスケジュールします。この構成では、hrスキーマへのすべての変更が伝播されることを指定しています。ルール・セットの指定を省略することもできますが、その場合はキュー内のすべてが伝播されます(これは、将来、複数の取得プロセスでstreams_queueを使用することになる場合には適していません)。

*/

BEGIN
-- Create the rule set
DBMS_RULE_ADM.CREATE_RULE_SET(
rule_set_name       => 'strmadmin.propagation_dbs1_rules',
evaluation_context  => 'SYS.STREAMS$_EVALUATION_CONTEXT');
-- Create rules for all modifications to the hr schema
DBMS_RULE_ADM.CREATE_RULE(
rule_name  => 'strmadmin.all_hr_dml',
condition  => ' :dml.get_object_owner() = ''HR'' AND ' ||
' :dml.is_null_tag() = ''Y'' AND ' ||
' :dml.get_source_database_name() = ''DBS1.EXAMPLE.COM'' ');
DBMS_RULE_ADM.CREATE_RULE(
rule_name  => 'strmadmin.all_hr_ddl',
condition  => ' (:ddl.get_object_owner() = ''HR'' OR ' ||
' :ddl.get_base_table_owner() =   ''HR'') AND ' ||
' :ddl.is_null_tag() = ''Y'' AND ' ||
' :ddl.get_source_database_name() = ''DBS1.EXAMPLE.COM'' ');
-- Add rules to rule set
DBMS_RULE_ADM.ADD_RULE(
rule_name      => 'strmadmin.all_hr_dml',
rule_set_name  => 'strmadmin.propagation_dbs1_rules');
DBMS_RULE_ADM.ADD_RULE(
rule_name      => 'strmadmin.all_hr_ddl',
rule_set_name  => 'strmadmin.propagation_dbs1_rules');
-- Create a propagation that uses the rule set as its positive rule set
DBMS_PROPAGATION_ADM.CREATE_PROPAGATION(
propagation_name    => 'dbs1_to_dbs2',
source_queue        => 'strmadmin.streams_queue',
destination_queue   => 'strmadmin.streams_queue',
destination_dblink  => 'dbs2.example.com',
rule_set_name       => 'strmadmin.propagation_dbs1_rules');
END;
/

/*

手順3: dbs1.example.comでの取得プロセスの構成

dbs1.example.comでhrスキーマ全体を取得する取得プロセスおよびルールを作成します。

*/

BEGIN
-- Create the rule set
DBMS_RULE_ADM.CREATE_RULE_SET(
rule_set_name       => 'strmadmin.demo_rules',
evaluation_context  => 'SYS.STREAMS$_EVALUATION_CONTEXT');
--   Create rules that specify the entire hr schema
DBMS_RULE_ADM.CREATE_RULE(
rule_name  => 'strmadmin.schema_hr_dml',
condition  => ' :dml.get_object_owner() = ''HR''  AND ' ||
' :dml.is_null_tag() = ''Y'' AND ' ||
' :dml.get_source_database_name() = ''DBS1.EXAMPLE.COM'' ');
DBMS_RULE_ADM.CREATE_RULE(
rule_name  => 'strmadmin.schema_hr_ddl',
condition  => ' (:ddl.get_object_owner() = ''HR'' OR ' ||
' :ddl.get_base_table_owner() =   ''HR'') AND ' ||
' :ddl.is_null_tag() = ''Y'' AND ' ||
' :ddl.get_source_database_name() = ''DBS1.EXAMPLE.COM'' ');
--  Add the rules to the rule set
DBMS_RULE_ADM.ADD_RULE(
rule_name      => 'strmadmin.schema_hr_dml',
rule_set_name  => 'strmadmin.demo_rules');
DBMS_RULE_ADM.ADD_RULE(
rule_name      => 'strmadmin.schema_hr_ddl',
rule_set_name  => 'strmadmin.demo_rules');
--  Create a capture process that uses the rule set as its positive rule set
DBMS_CAPTURE_ADM.CREATE_CAPTURE(
queue_name    => 'strmadmin.streams_queue',
capture_name  => 'capture',
rule_set_name => 'strmadmin.demo_rules');
END;
/

/*

手順4: dbs1.example.comでのhrスキーマのインスタンス化のための準備

dbs1.example.comにOracle Streams管理者として接続したままで、dbs3.example.comでdbs1.example.comのhrスキーマをインスタンス化のために準備します。この手順では、インスタンス化のためにスキーマ内の表の最小SCNにマークが付けられます。最小SCNより後のSCNは、インスタンス化に使用できます。

また、この手順では、hrスキーマ内の表のすべての主キー列、一意キー列、ビットマップ索引列および外部キー列のサプリメンタル・ロギングを有効にします。サプリメンタル・ロギングによって、表に対する変更の追加の情報がREDOログに記録されます。適用プロセスでは、一意の行の識別や競合解消など、一部の操作を実行するために、この追加情報が必要です。この環境では、dbs1.example.comデータベースでのみ変更が取得されるため、hrスキーマ内の表に対してサプリメンタル・ロギングを指定する必要があるのはこのデータベースのみです。

注意:
この手順は、「1つのデータベースからのデータを共有する簡単な構成」では不要です。その例では、手順3でDBMS_STREAMS_ADMパッケージのADD_SCHEMA_RULESプロシージャを実行するときに、DBMS_CAPTURE_ADMパッケージのPREPARE_SCHEMA_INSTANTIATIONプロシージャがhrスキーマに対して自動的に実行されます。

関連項目:
『Oracle Streamsレプリケーション管理者ガイド』

*/

BEGIN
DBMS_CAPTURE_ADM.PREPARE_SCHEMA_INSTANTIATION(
schema_name          => 'hr',
supplemental_logging => 'keys');
END;
/

/*

手順5: 他のデータベースでの既存の表に対するインスタンス化SCNの設定

この例では、dbs2.example.comおよびdbs4.example.comにhr.jobs表がすでに存在します。dbs2.example.comでは、この表の名前はassignmentsですが、この表はdbs1.example.comのjobs表と同じ形式で、同じデータを含んでいます。また、この例では、dbs4.example.comはSybaseデータベースです。Oracle Streams環境内の他のすべての表が、データ・ポンプ・インポートを使用して他の接続先データベースでインスタンス化されます。

hr.jobs表はdbs2.example.comおよびdbs4.example.comにすでに存在するため、この例ではdbs1.example.comでDBMS_FLASHBACKパッケージのGET_SYSTEM_CHANGE_NUMBERファンクションを使用して、データベースの現行のSCNを取得します。このSCNは、dbs2.example.comでDBMS_APPLY_ADMパッケージのSET_TABLE_INSTANTIATION_SCNプロシージャを実行するために使用されます。このプロシージャを2回実行して、dbs2.example.comおよびdbs4.example.comでhr.jobs表にインスタンス化SCNを設定します。

SET_TABLE_INSTANTIATION_SCNプロシージャを使用すると、適用プロセスで無視される表のLCRと、適用プロセスで適用される表のLCRを制御できます。ソース・データベースからの表に関するLCRのコミットSCNが、接続先データベースでその表のインスタンス化SCN以下であれば、接続先データベースの適用プロセスではLCRが廃棄されます。それ以外の場合は、適用プロセスによってLCRが適用されます。

この例では、dbs2.example.comの適用プロセスはいずれも、この手順で取得したSCNの後にコミットされたSCNを持つhr.jobs表にトランザクションを適用します。

注意:
この例では、dbs1.example.com、dbs2.example.com(hr.assignments)およびdbs4.example.comのhr.jobs表の内容は、この手順が完了した時点で一貫性があると想定しています。一貫性を確保するために、この手順の実行中に各データベースの表をロックすることをお薦めします。

*/

DECLARE
iscn  NUMBER;         -- Variable to hold instantiation SCN value
BEGIN
iscn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER();
DBMS_APPLY_ADM.SET_TABLE_INSTANTIATION_SCN@DBS2.EXAMPLE.COM(
source_object_name    => 'hr.jobs',
source_database_name  => 'dbs1.example.com',
instantiation_scn     => iscn);
DBMS_APPLY_ADM.SET_TABLE_INSTANTIATION_SCN@DBS2.EXAMPLE.COM(
source_object_name    => 'hr.jobs',
source_database_name  => 'dbs1.example.com',
instantiation_scn     => iscn,
apply_database_link   =>       'dbs4.example.com');
END;
/

/*

手順6: dbs3.example.comでのdbs1.example.comの表のインスタンス化

この例では、データ・ポンプを使用して次の表のネットワーク・インポートを実行します。

- hr.countries

- hr.locations

- hr.regions

ネットワーク・インポートとは、エクスポート・ダンプ・ファイルを使用せずに、データ・ポンプでdbs1.example.comからこれらの表をインポートすることを意味します。

関連項目:
インポートを実行する方法の詳細は、『Oracle Databaseユーティリティ』を参照してください。

strmadminユーザーとしてdbs3.example.comに接続します。

*/

CONNECT strmadmin@dbs3.example.com

/*

この例では、DBMS_DATAPUMPパッケージを使用して表のインポートを実行します。簡略化するために、どのAPIコールからの例外も捕捉されません。ただし、例外ハンドラを定義し、障害発生時にGET_STATUSをコールしてエラーの詳細情報を取得することをお薦めします。インポートを監視する場合は、インポート・データベースでDBA_DATAPUMP_JOBSデータ・ディクショナリ・ビューを問い合せます。

*/

SET SERVEROUTPUT ON
DECLARE
h1        NUMBER;         -- Data Pump job handle
sscn      NUMBER;         -- Variable to hold current source SCN
job_state VARCHAR2(30);   -- To keep track of job state
js        ku$_JobStatus;  -- The job status from GET_STATUS
sts       ku$_Status;     -- The status object returned by GET_STATUS
job_not_exist    exception;
pragma exception_init(job_not_exist, -31626);
BEGIN
-- Create a (user-named) Data Pump job to do a table-level import.
h1 := DBMS_DATAPUMP.OPEN(
operation   => 'IMPORT',
job_mode    => 'TABLE',
remote_link => 'DBS1.EXAMPLE.COM',
job_name    => 'dp_sing2');
-- A metadata filter is used to specify the schema that owns the tables
-- that will be imported.
DBMS_DATAPUMP.METADATA_FILTER(
handle    => h1,
name      => 'SCHEMA_EXPR',
value     => '=''HR''');
-- A metadata filter is used to specify the tables that will be imported.
DBMS_DATAPUMP.METADATA_FILTER(
handle    => h1,
name      => 'NAME_EXPR',
value     => 'IN(''COUNTRIES'', ''REGIONS'', ''LOCATIONS'')');
-- Get the current SCN of the source database, and set the FLASHBACK_SCN
-- parameter to this value to ensure consistency between all of the
-- objects included in the import.
sscn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER@dbs1.example.com();
DBMS_DATAPUMP.SET_PARAMETER(
handle => h1,
name   => 'FLASHBACK_SCN',
value  => sscn);
-- Start the job.
DBMS_DATAPUMP.START_JOB(h1);
-- The import job should be running. In the following loop, the job
-- is monitored until it completes.
job_state := 'UNDEFINED';
BEGIN
WHILE (job_state != 'COMPLETED') AND (job_state != 'STOPPED') LOOP
sts:=DBMS_DATAPUMP.GET_STATUS(
handle  => h1,
mask    => DBMS_DATAPUMP.KU$_STATUS_JOB_ERROR +
DBMS_DATAPUMP.KU$_STATUS_JOB_STATUS +
DBMS_DATAPUMP.KU$_STATUS_WIP,
timeout => -1);
js := sts.job_status;
DBMS_LOCK.SLEEP(10);
job_state := js.state;
END LOOP;
-- Gets an exception when job no longer exists
EXCEPTION WHEN job_not_exist THEN
DBMS_OUTPUT.PUT_LINE('Data Pump job has completed');
DBMS_OUTPUT.PUT_LINE('Instantiation SCN: ' ||sscn);
END;
END;
/

/*

手順7: dbs3.example.comでの適用プロセスの構成

strmadminユーザーとしてdbs3.example.comに接続します。

*/

CONNECT strmadmin@dbs3.example.com

/*

countries表、locations表およびregions表にDML変更およびDDL変更を適用するようにdbs3.example.comを構成します。

*/

BEGIN
-- Create the rule set
DBMS_RULE_ADM.CREATE_RULE_SET(
rule_set_name       => 'strmadmin.apply_rules',
evaluation_context  => 'SYS.STREAMS$_EVALUATION_CONTEXT');
-- Rules for hr.countries
DBMS_RULE_ADM.CREATE_RULE(
rule_name    => 'strmadmin.all_countries_dml',
condition    => ' :dml.get_object_owner() = ''HR'' AND ' ||
' :dml.get_object_name() = ''COUNTRIES''  AND ' ||
' :dml.is_null_tag() = ''Y'' AND ' ||
' :dml.get_source_database_name() = ''DBS1.EXAMPLE.COM'' ');
DBMS_RULE_ADM.CREATE_RULE(
rule_name    => 'strmadmin.all_countries_ddl',
condition    => ' (:ddl.get_object_owner() = ''HR'' OR ' ||
' :ddl.get_base_table_owner() =         ''HR'') AND ' ||
' :ddl.get_object_name() = ''COUNTRIES'' AND ' ||
' :ddl.is_null_tag() = ''Y'' AND ' ||
' :ddl.get_source_database_name() = ''DBS1.EXAMPLE.COM'' ');
-- Rules for hr.locations
DBMS_RULE_ADM.CREATE_RULE(
rule_name    => 'strmadmin.all_locations_dml',
condition    => ' :dml.get_object_owner() = ''HR'' AND ' ||
' :dml.get_object_name() = ''LOCATIONS'' AND ' ||
' :dml.is_null_tag() = ''Y'' AND ' ||
' :dml.get_source_database_name() = ''DBS1.EXAMPLE.COM'' ');
DBMS_RULE_ADM.CREATE_RULE(
rule_name    => 'strmadmin.all_locations_ddl',
condition    => ' (:ddl.get_object_owner() = ''HR'' OR ' ||
' :ddl.get_base_table_owner() =         ''HR'') AND ' ||
' :ddl.get_object_name() = ''LOCATIONS'' AND ' ||
' :ddl.is_null_tag() = ''Y'' AND ' ||
' :ddl.get_source_database_name() = ''DBS1.EXAMPLE.COM'' ');
-- Rules for hr.regions
DBMS_RULE_ADM.CREATE_RULE(
rule_name    => 'strmadmin.all_regions_dml',
condition    => ' :dml.get_object_owner() = ''HR'' AND ' ||
' :dml.get_object_name() = ''REGIONS'' AND ' ||
' :dml.is_null_tag() = ''Y'' AND ' ||
' :dml.get_source_database_name() = ''DBS1.EXAMPLE.COM'' ');
DBMS_RULE_ADM.CREATE_RULE(
rule_name    => 'strmadmin.all_regions_ddl',
condition    => ' (:ddl.get_object_owner() = ''HR'' OR ' ||
' :ddl.get_base_table_owner() =         ''HR'') AND ' ||
' :ddl.get_object_name() = ''REGIONS'' AND ' ||
' :ddl.is_null_tag() = ''Y'' AND ' ||
' :ddl.get_source_database_name() = ''DBS1.EXAMPLE.COM'' ');
-- Add rules to rule set
DBMS_RULE_ADM.ADD_RULE(
rule_name      => 'strmadmin.all_countries_dml',
rule_set_name  => 'strmadmin.apply_rules');
DBMS_RULE_ADM.ADD_RULE(
rule_name      => 'strmadmin.all_countries_ddl',
rule_set_name  => 'strmadmin.apply_rules');
DBMS_RULE_ADM.ADD_RULE(
rule_name      => 'strmadmin.all_locations_dml',
rule_set_name  => 'strmadmin.apply_rules');
DBMS_RULE_ADM.ADD_RULE(
rule_name      => 'strmadmin.all_locations_ddl',
rule_set_name  => 'strmadmin.apply_rules');
DBMS_RULE_ADM.ADD_RULE(
rule_name      => 'strmadmin.all_regions_dml',
rule_set_name  => 'strmadmin.apply_rules');
DBMS_RULE_ADM.ADD_RULE(
rule_name      => 'strmadmin.all_regions_ddl',
rule_set_name  => 'strmadmin.apply_rules');
-- Create an apply process that uses the rule set as its positive rule set
DBMS_APPLY_ADM.CREATE_APPLY(
queue_name      => 'strmadmin.streams_queue',
apply_name      => 'apply',
rule_set_name   => 'strmadmin.apply_rules',
apply_user      => 'hr',
apply_captured  => TRUE,
source_database => 'dbs1.example.com');
END;
/

/*

手順8: hrユーザーへの適用プロセスのルール・セットに対するEXECUTE権限の付与

前述の手順でhrユーザーを適用ユーザーとして指定したため、hrユーザーには、適用プロセスで使用されるポジティブ・ルール・セットに対するEXECUTE権限が必要です

*/

BEGIN
DBMS_RULE_ADM.GRANT_OBJECT_PRIVILEGE(
privilege   => SYS.DBMS_RULE_ADM.EXECUTE_ON_RULE_SET,
object_name => 'strmadmin.apply_rules',
grantee     => 'hr');
END;
/

/*

手順9: dbs3.example.comでの適用プロセスの起動

エラーが発生した場合に適用プロセスが無効化されないように、disable_on_errorパラメータをnに設定して、dbs3.example.comで適用プロセスを起動します。

*/

BEGIN
DBMS_APPLY_ADM.SET_PARAMETER(
apply_name  => 'apply',
parameter   => 'disable_on_error',
value       => 'N');
END;
/

BEGIN
DBMS_APPLY_ADM.START_APPLY(
apply_name  => 'apply');
END;
/

/*

手順10: dbs2.example.comでの伝播の構成

strmadminユーザーとしてdbs2.example.comに接続します。

*/

CONNECT strmadmin@dbs2.example.com

/*

dbs2.example.comのキューからdbs3.example.comのキューへの伝播を構成およびスケジュールします。dbs2.example.comの変更はdbs1.example.comで発生したものであるため、この構成は、有向ネットワークの一例です。

*/

BEGIN
-- Create the rule set
DBMS_RULE_ADM.CREATE_RULE_SET(
rule_set_name       => 'strmadmin.propagation_dbs3_rules',
evaluation_context  => 'SYS.STREAMS$_EVALUATION_CONTEXT');
-- Create rules for all modifications to the countries table
DBMS_RULE_ADM.CREATE_RULE(
rule_name  => 'strmadmin.all_countries_dml',
condition  => ' :dml.get_object_owner() = ''HR'' AND ' ||
' :dml.get_object_name() = ''COUNTRIES'' AND ' ||
' :dml.is_null_tag() = ''Y'' AND ' ||
' :dml.get_source_database_name() = ''DBS1.EXAMPLE.COM'' ');
DBMS_RULE_ADM.CREATE_RULE(
rule_name  => 'strmadmin.all_countries_ddl',
condition  => ' (:ddl.get_object_owner() = ''HR'' OR ' ||
' :ddl.get_base_table_owner() =   ''HR'') AND ' ||
' :ddl.get_object_name() = ''COUNTRIES'' AND ' ||
' :ddl.is_null_tag() = ''Y'' AND ' ||
' :ddl.get_source_database_name() = ''DBS1.EXAMPLE.COM'' ');
-- Create rules for all modifications to the locations table
DBMS_RULE_ADM.CREATE_RULE(
rule_name   => 'strmadmin.all_locations_dml',
condition  => ' :dml.get_object_owner() = ''HR'' AND ' ||
' :dml.get_object_name() = ''LOCATIONS'' AND ' ||
' :dml.is_null_tag() = ''Y'' AND ' ||
' :dml.get_source_database_name() = ''DBS1.EXAMPLE.COM'' ');
DBMS_RULE_ADM.CREATE_RULE(
rule_name   => 'strmadmin.all_locations_ddl',
condition  => ' (:ddl.get_object_owner() = ''HR'' OR ' ||
' :ddl.get_base_table_owner() =   ''HR'') AND ' ||
' :ddl.get_object_name() = ''LOCATIONS'' AND ' ||
' :ddl.is_null_tag() = ''Y'' AND ' ||
' :ddl.get_source_database_name() = ''DBS1.EXAMPLE.COM'' ');
-- Create rules for all modifications to the regions table
DBMS_RULE_ADM.CREATE_RULE(
rule_name   => 'strmadmin.all_regions_dml',
condition  => ' :dml.get_object_owner() = ''HR'' AND ' ||
' :dml.get_object_name() = ''REGIONS'' AND ' ||
' :dml.is_null_tag() = ''Y'' AND ' ||
' :dml.get_source_database_name() = ''DBS1.EXAMPLE.COM'' ');
DBMS_RULE_ADM.CREATE_RULE(
rule_name   => 'strmadmin.all_regions_ddl',
condition  => ' (:ddl.get_object_owner() = ''HR'' OR ' ||
' :ddl.get_base_table_owner() =   ''HR'') AND ' ||
' :ddl.get_object_name() = ''REGIONS'' AND ' ||
' :ddl.is_null_tag() = ''Y'' AND ' ||
' :ddl.get_source_database_name() = ''DBS1.EXAMPLE.COM'' ');
-- Add rules to rule set
DBMS_RULE_ADM.ADD_RULE(
rule_name      => 'strmadmin.all_countries_dml',
rule_set_name  => 'strmadmin.propagation_dbs3_rules');
DBMS_RULE_ADM.ADD_RULE(
rule_name      => 'strmadmin.all_countries_ddl',
rule_set_name  => 'strmadmin.propagation_dbs3_rules');
DBMS_RULE_ADM.ADD_RULE(
rule_name      => 'strmadmin.all_locations_dml',
rule_set_name  => 'strmadmin.propagation_dbs3_rules');
DBMS_RULE_ADM.ADD_RULE(
rule_name      => 'strmadmin.all_locations_ddl',
rule_set_name  => 'strmadmin.propagation_dbs3_rules');
DBMS_RULE_ADM.ADD_RULE(
rule_name      => 'strmadmin.all_regions_dml',
rule_set_name  => 'strmadmin.propagation_dbs3_rules');
DBMS_RULE_ADM.ADD_RULE(
rule_name      => 'strmadmin.all_regions_ddl',
rule_set_name  => 'strmadmin.propagation_dbs3_rules');
-- Create a propagation that uses the rule set as its positive rule set
DBMS_PROPAGATION_ADM.CREATE_PROPAGATION(
propagation_name    => 'dbs2_to_dbs3',
source_queue        => 'strmadmin.streams_queue',
destination_queue   => 'strmadmin.streams_queue',
destination_dblink  => 'dbs3.example.com',
rule_set_name       => 'strmadmin.propagation_dbs3_rules');
END;
/

/*

手順11: dbs2.example.comでの行LCRのカスタム・ルールベースの変換の作成

hrユーザーとしてdbs2.example.comに接続します。

*/

CONNECT hr@dbs2.example.com

/*

dbs1.example.comのjobs表に対するDML文によって発生する行変更をdbs2.example.comのassignments表に対する行変更に変換するカスタム・ルールベースの変換ファンクションを作成します。

次のファンクションを実行すると、jobs表のすべての行LCRがassignments表の行LCRに変換されます。

注意:
assignments表にDDL変更も適用された場合、DDL LCR用に別の変換が必要になります。この変換では、オブジェクト名およびDDLテキストを変更する必要があります。

*/

CREATE OR REPLACE FUNCTION hr.to_assignments_trans_dml(
p_in_data in ANYDATA)
RETURN ANYDATA IS out_data SYS.LCR$_ROW_RECORD;
tc   pls_integer;
BEGIN
-- Typecast AnyData to LCR$_ROW_RECORD
tc := p_in_data.GetObject(out_data);
IF out_data.GET_OBJECT_NAME() = 'JOBS'
THEN
-- Transform the in_data into the out_data
out_data.SET_OBJECT_NAME('ASSIGNMENTS');
END IF;
-- Convert to AnyData
RETURN ANYDATA.ConvertObject(out_data);
END;
/

/*

手順12: dbs2.example.comでのローカル適用を実行するための適用プロセスの構成

strmadminユーザーとしてdbs2.example.comに接続します。

*/

CONNECT strmadmin@dbs2.example.com

/*

ローカルのassignments表に変更を適用するようにdbs2.example.comを構成します。assignments表がdbs1.example.comのjobs表から変更を受信することに注意してください。この手順では、DBMS_STREAMS_ADMパッケージのSET_RULE_TRANSFORM_FUNCTIONプロシージャを使用せずにカスタム・ルールベースの変換を指定します。かわりに、名前/値ペアをルールのアクション・コンテキストに手動で追加します。名前/値ペアでは、名前にSTREAMS$_TRANSFORM_FUNCTION、値にhr.to_assignments_trans_dmlが指定されます。

*/

DECLARE
action_ctx_dml       SYS.RE$NV_LIST;
action_ctx_ddl       SYS.RE$NV_LIST;
ac_name              VARCHAR2(30) := 'STREAMS$_TRANSFORM_FUNCTION';
BEGIN
-- Specify the name-value pair in the action context
action_ctx_dml := SYS.RE$NV_LIST(SYS.RE$NV_ARRAY());
action_ctx_dml.ADD_PAIR(
ac_name,
ANYDATA.CONVERTVARCHAR2('hr.to_assignments_trans_dml'));
--  Create the rule set strmadmin.apply_rules
DBMS_RULE_ADM.CREATE_RULE_SET(
rule_set_name       => 'strmadmin.apply_rules',
evaluation_context  => 'SYS.STREAMS$_EVALUATION_CONTEXT');
--  Create a rule that transforms all DML changes to the jobs table into
--  DML changes for assignments table
DBMS_RULE_ADM.CREATE_RULE(
rule_name       => 'strmadmin.all_jobs_dml',
condition       => ' :dml.get_object_owner() = ''HR'' AND ' ||
' :dml.get_object_name() = ''JOBS'' AND ' ||
' :dml.is_null_tag() = ''Y'' AND ' ||
' :dml.get_source_database_name() = ''DBS1.EXAMPLE.COM'' ',
action_context  => action_ctx_dml);
--  Add the rule to the rule set
DBMS_RULE_ADM.ADD_RULE(
rule_name      => 'strmadmin.all_jobs_dml',
rule_set_name  => 'strmadmin.apply_rules');
-- Create an apply process that uses the rule set as its positive rule set
DBMS_APPLY_ADM.CREATE_APPLY(
queue_name      => 'strmadmin.streams_queue',
apply_name      => 'apply_dbs2',
rule_set_name   => 'strmadmin.apply_rules',
apply_user      => 'hr',
apply_captured  => TRUE,
source_database => 'dbs1.example.com');
END;
/

/*

手順13: hrユーザーへの適用プロセスのルール・セットに対するEXECUTE権限の付与

前述の手順でhrユーザーを適用ユーザーとして指定したため、hrユーザーには、適用プロセスで使用されるポジティブ・ルール・セットに対するEXECUTE権限が必要です

*/

BEGIN
DBMS_RULE_ADM.GRANT_OBJECT_PRIVILEGE(
privilege   => SYS.DBMS_RULE_ADM.EXECUTE_ON_RULE_SET,
object_name => 'strmadmin.apply_rules',
grantee     => 'hr');
END;
/

/*

手順14: dbs2.example.comでのローカル適用を実行するための適用プロセスの起動

エラーが発生した場合に適用プロセスが無効化されないように、disable_on_errorパラメータをnに設定して、dbs2.example.comでローカル適用を実行するために適用プロセスを起動します。

*/

BEGIN
DBMS_APPLY_ADM.SET_PARAMETER(
apply_name  => 'apply_dbs2',
parameter   => 'disable_on_error',
value       => 'N');
END;
/

BEGIN
DBMS_APPLY_ADM.START_APPLY(
apply_name  => 'apply_dbs2');
END;
/

/*

手順15: dbs4.example.comでの適用を実行するためのdbs2.example.comでの適用プロセスの構成

dbs4.example.com(Sybaseデータベース)のjobs表にDML変更を適用するようにdbs2.example.comを構成します。この変更はdbs1.example.comで発生したことに注意してください。

*/

BEGIN
-- Create the rule set
DBMS_RULE_ADM.CREATE_RULE_SET(
rule_set_name      => 'strmadmin.apply_dbs4_rules',
evaluation_context => 'SYS.STREAMS$_EVALUATION_CONTEXT');
-- Create rule strmadmin.all_jobs_remote for all modifications
-- to the jobs table
DBMS_RULE_ADM.CREATE_RULE(
rule_name    => 'strmadmin.all_jobs_remote',
condition    => ' :dml.get_object_owner() = ''HR'' AND ' ||
' :dml.get_object_name() = ''JOBS'' AND ' ||
' :dml.is_null_tag() = ''Y'' AND ' ||
' :dml.get_source_database_name() = ''DBS1.EXAMPLE.COM'' ');
-- Add the rule to the rule set
DBMS_RULE_ADM.ADD_RULE(
rule_name      => 'strmadmin.all_jobs_remote',
rule_set_name  => 'strmadmin.apply_dbs4_rules');
-- Create an apply process that uses the rule set as its positive rule set
DBMS_APPLY_ADM.CREATE_APPLY(
queue_name          => 'strmadmin.streams_queue',
apply_name          => 'apply_dbs4',
rule_set_name       => 'strmadmin.apply_dbs4_rules',
apply_database_link => 'dbs4.example.com',
apply_captured      => TRUE,
source_database     => 'dbs1.example.com');
END;
/

/*

手順16: dbs4.example.comでの適用を実行するためのdbs2.example.comでの適用プロセスの起動

エラーが発生した場合に適用プロセスが無効化されないように、disable_on_errorパラメータをnに設定して、データベース・リンクdbs4.example.comを使用してSybaseのリモート適用を開始します。

*/

BEGIN
DBMS_APPLY_ADM.SET_PARAMETER(
apply_name  => 'apply_dbs4',
parameter   => 'disable_on_error',
value       => 'N');
END;
/

BEGIN
DBMS_APPLY_ADM.START_APPLY(
apply_name  => 'apply_dbs4');
END;
/

/*

手順17: dbs1.example.comでの取得プロセスの起動

strmadminユーザーとしてdbs1.example.comに接続します。

*/

CONNECT strmadmin@dbs1.example.com

/*

dbs1.example.comで取得プロセスを起動します。

*/

BEGIN
DBMS_CAPTURE_ADM.START_CAPTURE(
capture_name  => 'capture');
END;
/

/*

手順18: スプール結果のチェック

streams_share_schema2.outスプール・ファイルをチェックして、このスクリプトの完了後にすべてのアクションが正常に終了していることを確認します。

*/

SET ECHO OFF
SPOOL OFF

/*

ここで、dbs1.example.comの特定の表に対してDML変更およびDDL変更を行い、この環境内のOracle Streamsプロセスおよび伝播について構成したルールに基づいて、環境内の他のデータベースにこれらの変更がレプリケートされていることを確認できます。

関連項目:
この環境内でレプリケートされる変更の例については、「hrスキーマ内の表に対するDML変更およびDDL変更」を参照してください。

/*************************** END OF SCRIPT ******************************/

hrスキーマ内の表に対するDML変更およびDDL変更

「1つのデータベースからのデータを共有するスクリプトの例」で説明したいずれかの例を完了した後に、dbs1.example.comデータベースのhrスキーマ内の表に対してDML変更およびDDL変更を行うことができます。これらの変更は、Oracle Streamsプロセスおよび伝播について構成したルールに基づいて、環境内の他のデータベースにレプリケートされます。他のデータベースをチェックして、変更がレプリケートされていることを確認できます。

たとえば、次の手順を実行して、dbs1.example.comのhr.jobsおよびhr.locations表に対してDML変更を行います。また、dbs1.example.comのhr.locations表に対してDDL変更を行うこともできます。

これらの変更を行った後に、dbs2.example.comでhr.assignments表を問い合せて、dbs1.example.comのこの表に対して行ったDML変更がレプリケートされていることを確認できます。dbs2.example.comの適用プロセスに構成したカスタム・ルールベースの変換によって、hr.jobs表に対するDML変更がhr.assignments表に対するDML変更に変換されていることに注意してください。dbs3.example.comでhr.locations表を問い合せて、dbs1.example.comのこの表に対して行ったDML変更およびDDL変更がレプリケートされていることも確認できます。

手順1: hrスキーマ内の表に対するDML変更およびDDL変更

次の変更を行います。

CONNECT hr@dbs1.example.com
Enter password: password

UPDATE hr.jobs SET max_salary=10000 WHERE job_id='MK_REP';
COMMIT;

INSERT INTO hr.locations VALUES(
3300, '521 Ralston Avenue', '94002', 'Belmont', 'CA', 'US');
COMMIT;

ALTER TABLE hr.locations RENAME COLUMN state_province TO state_or_province;

手順2: dbs2.example.comでのhr.assignments表の問合せ

前述の手順で行った変更が取得、伝播および適用されてから、次の問合せを実行して、dbs1.example.comのhr.jobs表に対して行ったUPDATE変更がdbs2.example.comのhr.assignments表に適用されていることを確認します。

CONNECT hr@dbs2.example.com
Enter password: password

SELECT max_salary FROM hr.assignments WHERE job_id='MK_REP';

max_salaryの値が10000と表示されるはずです。

手順3: dbs3.example.comでのhr.locations表の問合せおよび定義の表示

次の問合せを実行して、dbs1.example.comのhr.locations表に対して行ったINSERT変更がdbs3.example.comで適用されていることを確認します。

CONNECT hr@dbs3.example.com
Enter password: password

SELECT * FROM hr.locations WHERE location_id=3300;

前述の手順でdbs1.example.comのhr.locations表に挿入した行が表示されるはずです。

次に、hr.locations表の定義を表示して、ALTER TABLE変更が正常に伝播および適用されていることを確認します。

DESC hr.locations

表の5列目がstate_or_provinceであるはずです。

既存のOracle Streamsレプリケーション環境へのオブジェクトの追加

この例では、レプリケート・オブジェクトを既存のデータベースに追加して、前項で構成したOracle Streams環境を拡張します。この例を実行するには、前述の例のいずれか一方のタスクを完了している必要があります。

この例では、dbs3.example.comデータベースのhrスキーマに次の表を追加します。

- departments

- employees

- job_history

- jobs

この例を完了すると、Oracle Streamsでは、これらの表に対する変更が次の一連のアクションで処理されます。

1. 取得プロセスがdbs1.example.comで変更を取得してdbs1.example.comでエンキューします。

2. 伝播によって、dbs1.example.comのキューからdbs2.example.comのキューに変更が伝播されます。

3. 伝播によって、dbs2.example.comのキューからdbs3.example.comのキューに変更が伝播されます。

4. dbs3.example.comの適用プロセスが、変更をdbs3.example.comで適用します。

この例を完了すると、countries表、locations表およびregions表は前項でdbs3.example.comでインスタンス化されているため、dbs3.example.comデータベースのhrスキーマにはオリジナルの表がすべて含まれることになります。

図2-2に、表が追加された環境の概要を示します。

図2-2 環境内のdbs3.example.comへのオブジェクトの追加

次の手順を実行して、前述の表をdbs3.example.comデータベースにレプリケートします。

1. 出力およびスプール結果の表示

2. dbs3.example.comでの適用プロセスの停止

3. dbs3.example.comでの追加する表に対する適用プロセスの構成

4. dbs2.example.comでの追加する表に対する表の伝播ルールの指定

5. dbs1.example.comでの追加する4つの表のインスタンス化のための準備

6. dbs3.example.comでのdbs1.example.comの表のインスタンス化

7. dbs3.example.comでの適用プロセスの起動

8. スプール結果のチェック

注意:
このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。

/************************* BEGINNING OF SCRIPT ******************************

手順1: 出力およびスプール結果の表示

SET ECHO ONを実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。

*/

SET ECHO ON
SPOOL streams_addobjs.out

/*

手順2: dbs3.example.comでの適用プロセスの停止

dbs3.example.comへのオブジェクトの追加が完了するまで、追加するオブジェクトの適用プロセスによって、これらのオブジェクトの変更が適用されないようにする必要があります。そのために、ソース・データベースで取得プロセスを停止できます。または、dbs2.example.comからdbs3.example.comへの変更の伝播を停止できます。さらに、dbs3.example.comで適用プロセスを停止することもできます。この例では、dbs3.example.comで適用プロセスを停止します。

strmadminユーザーとしてdbs3.example.comに接続します。

*/

CONNECT strmadmin@dbs3.example.com

/*

dbs3.example.comで適用プロセスを停止します。

*/

BEGIN
DBMS_APPLY_ADM.STOP_APPLY(
apply_name  => 'apply');
END;
/

/*

手順3: dbs3.example.comでの追加する表に対する適用プロセスの構成

追加する表に変更を適用するように、dbs3.example.comで適用プロセスを構成します。

*/

BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name      => 'hr.departments',
streams_type    => 'apply',
streams_name    => 'apply',
queue_name      => 'strmadmin.streams_queue',
include_dml     => TRUE,
include_ddl     => TRUE,
source_database => 'dbs1.example.com',
inclusion_rule  => TRUE);
END;
/

BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name      => 'hr.employees',
streams_type    => 'apply',
streams_name    => 'apply',
queue_name      => 'strmadmin.streams_queue',
include_dml     => TRUE,
include_ddl     => TRUE,
source_database => 'dbs1.example.com',
inclusion_rule  => TRUE);
END;
/

BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name      => 'hr.job_history',
streams_type    => 'apply',
streams_name    => 'apply',
queue_name      => 'strmadmin.streams_queue',
include_dml     => TRUE,
include_ddl     => TRUE,
source_database => 'dbs1.example.com',
inclusion_rule  => TRUE);
END;
/

BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name      => 'hr.jobs',
streams_type    => 'apply',
streams_name    => 'apply',
queue_name      => 'strmadmin.streams_queue',
include_dml     => TRUE,
include_ddl     => TRUE,
source_database => 'dbs1.example.com',
inclusion_rule  => TRUE);
END;
/

/*

手順4: dbs2.example.comでの追加する表に対する表の伝播ルールの指定

strmadminユーザーとしてdbs2.example.comに接続します。

*/

CONNECT strmadmin@dbs2.example.com

/*

dbs2.example.comのキューからdbs3.example.comのキューへの伝播のルールに表を追加します。

*/

BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_PROPAGATION_RULES(
table_name               => 'hr.departments',
streams_name             => 'dbs2_to_dbs3',
source_queue_name        => 'strmadmin.streams_queue',
destination_queue_name   => 'strmadmin.streams_queue@dbs3.example.com',
include_dml              => TRUE,
include_ddl              => TRUE,
source_database          => 'dbs1.example.com',
inclusion_rule           => TRUE);
END;
/

BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_PROPAGATION_RULES(
table_name              => 'hr.employees',
streams_name            => 'dbs2_to_dbs3',
source_queue_name       => 'strmadmin.streams_queue',
destination_queue_name  => 'strmadmin.streams_queue@dbs3.example.com',
include_dml             => TRUE,
include_ddl             => TRUE,
source_database         => 'dbs1.example.com',
inclusion_rule          => TRUE);
END;
/

BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_PROPAGATION_RULES(
table_name              => 'hr.job_history',
streams_name            => 'dbs2_to_dbs3',
source_queue_name       => 'strmadmin.streams_queue',
destination_queue_name  => 'strmadmin.streams_queue@dbs3.example.com',
include_dml             => TRUE,
include_ddl             => TRUE,
source_database         => 'dbs1.example.com',
inclusion_rule          => TRUE);
END;
/

BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_PROPAGATION_RULES(
table_name              => 'hr.jobs',
streams_name            => 'dbs2_to_dbs3',
source_queue_name       => 'strmadmin.streams_queue',
destination_queue_name  => 'strmadmin.streams_queue@dbs3.example.com',
include_dml             => TRUE,
include_ddl             => TRUE,
source_database         => 'dbs1.example.com',
inclusion_rule          => TRUE);
END;
/

/*

手順5: dbs1.example.comでの追加する4つの表のインスタンス化のための準備

strmadminユーザーとしてdbs1.example.comに接続します。

*/

CONNECT strmadmin@dbs1.example.com

/*

表をインスタンス化のために準備します。これらの表は、dbs3.example.comでインスタンス化されます。この手順では、インスタンス化のために表の最小SCNにマークが付けられます。最小SCNより後のSCNは、インスタンス化に使用できます。この準備は、dbs3.example.comで関連する伝播および適用プロセスのOracle Streamsデータ・ディクショナリにこれらの表の情報を含めるためにも必要です。

注意:
この手順でPREPARE_TABLE_INSTANTIATIONプロシージャを実行する際、supplemental_loggingパラメータは指定しません。したがって、このパラメータにはデフォルト値(keys)が使用されます。サプリメンタル・ロギングは、これらの表のすべての主キー列、一意キー列、ビットマップ索引列および外部キー列について、手順3ですでに有効化されています。

関連項目:
『Oracle Streamsレプリケーション管理者ガイド』

*/

BEGIN
DBMS_CAPTURE_ADM.PREPARE_TABLE_INSTANTIATION(
table_name  => 'hr.departments');
END;
/

BEGIN
DBMS_CAPTURE_ADM.PREPARE_TABLE_INSTANTIATION(
table_name  => 'hr.employees');
END;
/

BEGIN
DBMS_CAPTURE_ADM.PREPARE_TABLE_INSTANTIATION(
table_name  => 'hr.job_history');
END;
/

BEGIN
DBMS_CAPTURE_ADM.PREPARE_TABLE_INSTANTIATION(
table_name  => 'hr.jobs');
END;
/

/*

手順6: dbs3.example.comでのdbs1.example.comの表のインスタンス化

この例では、データ・ポンプを使用して次の表のネットワーク・インポートを実行します。

- hr.departments

- hr.employees

- hr.job_history

- hr.jobs

ネットワーク・インポートとは、エクスポート・ダンプ・ファイルを使用せずに、データ・ポンプでdbs1.example.comからこれらの表をインポートすることを意味します。

関連項目:
インポートを実行する方法の詳細は、『Oracle Databaseユーティリティ』を参照してください。

strmadminユーザーとしてdbs3.example.comに接続します。

*/

CONNECT strmadmin@dbs3.example.com

/*

この例では、DBMS_DATAPUMPパッケージを使用して表のインポートを実行します。簡略化するために、どのAPIコールからの例外も捕捉されません。ただし、例外ハンドラを定義し、障害発生時にGET_STATUSをコールしてエラーの詳細情報を取得することをお薦めします。インポートを監視する場合は、インポート・データベースでDBA_DATAPUMP_JOBSデータ・ディクショナリ・ビューを問い合せます。

*/

SET SERVEROUTPUT ON
DECLARE
h1        NUMBER;         -- Data Pump job handle
sscn      NUMBER;         -- Variable to hold current source SCN
job_state VARCHAR2(30);   -- To keep track of job state
js        ku$_JobStatus;  -- The job status from GET_STATUS
sts       ku$_Status;     -- The status object returned by GET_STATUS
job_not_exist    exception;
pragma exception_init(job_not_exist, -31626);
BEGIN
-- Create a (user-named) Data Pump job to do a table-level import.
h1 := DBMS_DATAPUMP.OPEN(
operation   => 'IMPORT',
job_mode    => 'TABLE',
remote_link => 'DBS1.EXAMPLE.COM',
job_name    => 'dp_sing3');
-- A metadata filter is used to specify the schema that owns the tables
-- that will be imported.
DBMS_DATAPUMP.METADATA_FILTER(
handle    => h1,
name      => 'SCHEMA_EXPR',
value     => '=''HR''');
-- A metadata filter is used to specify the tables that will be imported.
DBMS_DATAPUMP.METADATA_FILTER(
handle    => h1,
name      => 'NAME_EXPR',
value     => 'IN(''DEPARTMENTS'', ''EMPLOYEES'',
''JOB_HISTORY'', ''JOBS'')');
-- Get the current SCN of the source database, and set the FLASHBACK_SCN
-- parameter to this value to ensure consistency between all of the
-- objects included in the import.
sscn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER@dbs1.example.com();
DBMS_DATAPUMP.SET_PARAMETER(
handle => h1,
name   => 'FLASHBACK_SCN',
value  => sscn);
-- Start the job.
DBMS_DATAPUMP.START_JOB(h1);
-- The import job should be running. In the following loop, the job
-- is monitored until it completes.
job_state := 'UNDEFINED';
BEGIN
WHILE (job_state != 'COMPLETED') AND (job_state != 'STOPPED') LOOP
sts:=DBMS_DATAPUMP.GET_STATUS(
handle  => h1,
mask    => DBMS_DATAPUMP.KU$_STATUS_JOB_ERROR +
DBMS_DATAPUMP.KU$_STATUS_JOB_STATUS +
DBMS_DATAPUMP.KU$_STATUS_WIP,
timeout => -1);
js := sts.job_status;
DBMS_LOCK.SLEEP(10);
job_state := js.state;
END LOOP;
-- Gets an exception when job no longer exists
EXCEPTION WHEN job_not_exist THEN
DBMS_OUTPUT.PUT_LINE('Data Pump job has completed');
DBMS_OUTPUT.PUT_LINE('Instantiation SCN: ' ||sscn);
END;
END;
/

/*

手順7: dbs3.example.comでの適用プロセスの起動

dbs3.example.comで適用プロセスを起動します。これは、手順2で停止した適用プロセスです。

strmadminユーザーとしてdbs3.example.comに接続します。

*/

CONNECT strmadmin@dbs3.example.com

/*

dbs3.example.comで適用プロセスを起動します。

*/

BEGIN
DBMS_APPLY_ADM.START_APPLY(
apply_name  => 'apply');
END;
/

/*

手順8: スプール結果のチェック

streams_addobjs.outスプール・ファイルをチェックして、このスクリプトの完了後にすべてのアクションが正常に終了していることを確認します。

*/

SET ECHO OFF
SPOOL OFF

/*************************** END OF SCRIPT ******************************/

hr.employees表に対するDML変更

「既存のOracle Streamsレプリケーション環境へのオブジェクトの追加」で説明した例を完了した後に、dbs1.example.comデータベースのhrスキーマ内の表に対してDML変更およびDDL変更を行うことができます。これらの変更は、dbs3.example.comにレプリケートされます。dbs3.example.comでこれらの表をチェックして、変更がレプリケートされていることを確認できます。

たとえば、次の手順を実行して、dbs1.example.comのhr.employees表に対してDML変更を行います。次に、dbs3.example.comでhr.employees表を問い合せて、変更がレプリケートされていることを確認します。

手順1: hr.employees表に対するDML変更

次の変更を行います。

CONNECT hr@dbs1.example.com
Enter password: password

UPDATE hr.employees SET job_id='ST_MAN' WHERE employee_id=143;
COMMIT;

手順2: dbs3.example.comでのhr.employees表の問合せ

前述の手順で行った変更が取得、伝播および適用されてから、次の問合せを実行して、dbs1.example.comのhr.employees表に対して行ったUPDATE変更がdbs3.example.comのhr.employees表に適用されていることを確認します。

CONNECT hr@dbs3.example.com
Enter password: password

SELECT job_id FROM hr.employees WHERE employee_id=143;

job_idの値がST_MANと表示されるはずです。

既存のOracle Streamsレプリケーション環境へのデータベースの追加

この例では、既存の構成にデータベースを追加して、前項で構成したOracle Streams環境を拡張します。この例では、dbs2.example.comのキューからhrスキーマ全体に対する変更を受信するために、既存のOracle Database dbs5.example.comを追加します。

図2-3に、データベースが追加された環境の概要を示します。

図2-3 環境へのOracle Database dbs5.example.comの追加

この例を完了するには、次の前提条件を満たしている必要があります。

- dbs5.example.comデータベースが存在すること。

- dbs2.example.comおよびdbs5.example.comデータベースがOracle Netを介して相互に通信できること。

- dbs5.example.comおよびdbs1.example.comデータベースがOracle Netを介して相互に通信できること(オプションのデータ・ポンプ・ネットワークのインスタンス化のため)。

- この章の前述の例のタスクを完了していること。

- Oracle Streams環境全体を正常に機能させる場合は、「前提条件」を満たしていること。

- この例では、dbs5.example.comデータベースで新規ユーザーがOracle Streams管理者(strmadmin)として作成され、このユーザーのデータに使用する表領域の指定を求めるプロンプトが表示されます。この例を開始する前に、dbs5.example.comデータベースでOracle Streams管理者用に新規の表領域を作成するか、または既存の表領域を識別してください。SYSTEM表領域は、Oracle Streams管理者用にしないでください。

次の手順を実行して、dbs5.example.comをOracle Streams環境に追加します。

1. 出力およびスプール結果の表示

2. dbs5.example.comでのhrスキーマ内のすべての表の削除

3. dbs5.example.comでのユーザーの設定

4. dbs5.example.comでのANYDATAキューの作成

5. dbs5.example.comからdbs1.example.comへのデータベース・リンクの作成

6. dbs5.example.comでの適用プロセスの構成

7. dbs5.example.comでの適用プロセスの適用ユーザーとしてのhrの指定

8. hrユーザーへの適用プロセスのルール・セットに対するEXECUTE権限の付与

9. dbs2.example.comとdbs5.example.comの間のデータベース・リンクの作成

10. dbs2.example.comとdbs5.example.comの間の伝播の構成

11. dbs1.example.comでのhrスキーマのインスタンス化のための準備

12. dbs5.example.comでのdbs1.example.comの表のインスタンス化

13. dbs5.example.comでの適用プロセスの起動

14. スプール結果のチェック

注意:
このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。

/************************* BEGINNING OF SCRIPT ******************************

手順1: 出力およびスプール結果の表示

SET ECHO ONを実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。

*/

SET ECHO ON
SPOOL streams_adddb.out

/*

手順2: dbs5.example.comでのhrスキーマ内のすべての表の削除

この例では、データ・ポンプを使用してdbs1.example.comからdbs5.example.comに表をインポートすることによって、hrスキーマ内の表をインスタンス化する方法について説明します。この例でのインスタンス化を正常に実行するために、dbs5.example.comでこれらの表を削除する必要があります。

hrとしてdbs5.example.comに接続します。

*/

CONNECT hr@dbs5.example.com

/*

dbs5.example.comデータベースのhrスキーマ内のすべての表を削除します。

注意:
この手順を実行してhrスキーマ内のすべての表を削除した場合、この例の残りの項の手順を実行して、dbs5.example.comでhrスキーマを再インスタンス化する必要があります。hrスキーマがOracle Databaseに存在しない場合、Oracleマニュアル・セットの一部の例が失敗する可能性があります。

*/

DROP TABLE hr.countries CASCADE CONSTRAINTS;
DROP TABLE hr.departments CASCADE CONSTRAINTS;
DROP TABLE hr.employees CASCADE CONSTRAINTS;
DROP TABLE hr.job_history CASCADE CONSTRAINTS;
DROP TABLE hr.jobs CASCADE CONSTRAINTS;
DROP TABLE hr.locations CASCADE CONSTRAINTS;
DROP TABLE hr.regions CASCADE CONSTRAINTS;

/*

手順3: dbs5.example.comでのユーザーの設定

SYSTEMユーザーとしてdbs5.example.comに接続します。

*/

CONNECT system@dbs5.example.com

/*

Oracle Streams管理者strmadminを作成し、このユーザーに必要な権限を付与します。これらの権限によって、ユーザーは、キューの管理、Oracle Streamsに関連するパッケージのサブプログラムの実行、ルール・セットおよびルールの作成、データ・ディクショナリ・ビューおよびキュー表の問合せによるOracle Streams環境の監視を行うことができるようになります。このユーザーには、異なる名前を指定できます。

注意:
ACCEPTコマンドを、スクリプト内の1行に指定する必要があります。

関連項目:
Oracle Streams管理者を構成する方法の詳細は、『Oracle Streamsレプリケーション管理者ガイド』を参照してください。

*/

ACCEPT password PROMPT 'Enter password for user: ' HIDE

GRANT DBA TO strmadmin IDENTIFIED BY &password;

ACCEPT streams_tbs PROMPT 'Enter Oracle Streams administrator tablespace on dbs5.example.com: ' HIDE

ALTER USER strmadmin DEFAULT TABLESPACE &streams_tbs
QUOTA UNLIMITED ON &streams_tbs;

/*

手順4: dbs5.example.comでのANYDATAキューの作成

Oracle Streams管理者として追加するデータベースに接続します。この例では、データベースdbs5.example.comに接続します。

*/

CONNECT strmadmin@dbs5.example.com

/*

SET_UP_QUEUEプロシージャを実行して、dbs5.example.comでstreams_queueというキューを作成します。このキューはANYDATAキューとして動作し、このデータベースに適用される変更を保持します。

SET_UP_QUEUEプロシージャを実行すると、次のアクションが実行されます。

- streams_queue_tableというキュー表の作成。このキュー表は、Oracle Streams管理者(strmadmin)が所有し、このユーザーのデフォルトの記憶域を使用します。

- Oracle Streams管理者(strmadmin)が所有するstreams_queueというキューの作成。

- キューの起動。

*/

EXEC  DBMS_STREAMS_ADM.SET_UP_QUEUE();

/*

手順5: dbs5.example.comからdbs1.example.comへのデータベース・リンクの作成

dbs5.example.comからdbs1.example.comへのデータベース・リンクを作成します。このデータベース・リンクは、この例の後半で、手順2で削除したデータベース・オブジェクトをインスタンス化するために使用します。この例では、DBMS_DATAPUMPパッケージを使用して、dbs1.example.comデータベースから直接これらのデータベース・オブジェクトのネットワーク・インポートを実行します。この例ではネットワーク・インポートを実行するため、ダンプ・ファイルは不要です。

または、ソース・データベースdbs1.example.comでエクスポートを実行し、エクスポート・ダンプ・ファイルを接続先データベースdbs5.example.comに転送して、接続先データベースでエクスポート・ダンプ・ファイルをインポートすることもできます。この場合、この手順で作成するデータベース・リンクは不要です。

*/

CREATE DATABASE LINK dbs1.example.com CONNECT TO strmadmin
IDENTIFIED BY &password USING 'dbs1.example.com';

/*

手順6: dbs5.example.comでの適用プロセスの構成

dbs5.example.comにOracle Streams管理者として接続したままで、hrスキーマに変更を適用するように適用プロセスを構成します。

*/

BEGIN
DBMS_STREAMS_ADM.ADD_SCHEMA_RULES(
schema_name     => 'hr',
streams_type    => 'apply',
streams_name    => 'apply',
queue_name      => 'strmadmin.streams_queue',
include_dml     => TRUE,
include_ddl     => TRUE,
source_database => 'dbs1.example.com',
inclusion_rule  => TRUE);
END;
/

/*

手順7: dbs5.example.comでの適用プロセスの適用ユーザーとしてのhrの指定

この例では、hrユーザーが、このデータベースで適用プロセスによって変更が適用されるすべてのデータベース・オブジェクトを所有します。したがって、hrはこれらのデータベース・オブジェクトを変更するために必要な権限をすでに持っており、hrを適用ユーザーにすることが有効です。

前述の手順で適用プロセスを作成したときに、適用プロセスを作成したプロシージャをOracle Streams管理者strmadminが実行したため、デフォルトでは、strmadminが適用ユーザーとして指定されています。hrを適用ユーザーとして指定するかわりに、strmadminを適用ユーザーのままにしておくこともできますが、この場合、変更が適用されるすべてのデータベース・オブジェクトに対する権限、および適用プロセスで使用されるすべてのユーザー・プロシージャを実行する権限をstrmadminに付与する必要があります。適用プロセスが複数のスキーマ内のデータベース・オブジェクトに変更を適用する環境では、Oracle Streams管理者を適用ユーザーとして使用する方が有効な場合があります。

関連項目:
Oracle Streams管理者を構成する方法の詳細は、『Oracle Streamsレプリケーション管理者ガイド』を参照してください。

*/

BEGIN
DBMS_APPLY_ADM.ALTER_APPLY(
apply_name => 'apply',
apply_user => 'hr');
END;
/

/*

手順8: hrユーザーへの適用プロセスのルール・セットに対するEXECUTE権限の付与

前述の手順でhrユーザーを適用ユーザーとして指定したため、hrユーザーには、適用プロセスで使用されるポジティブ・ルール・セットに対するEXECUTE権限が必要です

*/

DECLARE
rs_name  VARCHAR2(64);   -- Variable to hold rule set name
BEGIN
SELECT RULE_SET_OWNER||'.'||RULE_SET_NAME
INTO rs_name
FROM DBA_APPLY
WHERE APPLY_NAME='APPLY';
DBMS_RULE_ADM.GRANT_OBJECT_PRIVILEGE(
privilege   => SYS.DBMS_RULE_ADM.EXECUTE_ON_RULE_SET,
object_name => rs_name,
grantee     => 'hr');
END;
/

/*

手順9: dbs2.example.comとdbs5.example.comの間のデータベース・リンクの作成

strmadminユーザーとしてdbs2.example.comに接続します。

*/

CONNECT strmadmin@dbs2.example.com

/*

変更が伝播されるデータベースへのデータベース・リンクを作成します。この例では、データベースdbs2.example.comがdbs5.example.comに変更を伝播します。

*/

CREATE DATABASE LINK dbs5.example.com CONNECT TO strmadmin
IDENTIFIED BY &password USING 'dbs5.example.com';

/*

手順10: dbs2.example.comとdbs5.example.comの間の伝播の構成

dbs2.example.comにOracle Streams管理者として接続したままで、dbs2.example.comのキューからdbs5.example.comのキューへの伝播を構成およびスケジュールします。hrスキーマに対する変更はdbs1.example.comで発生したことに注意してください。

*/

BEGIN
DBMS_STREAMS_ADM.ADD_SCHEMA_PROPAGATION_RULES(
schema_name             => 'hr',
streams_name            => 'dbs2_to_dbs5',
source_queue_name       => 'strmadmin.streams_queue',
destination_queue_name  => 'strmadmin.streams_queue@dbs5.example.com',
include_dml             => TRUE,
include_ddl             => TRUE,
source_database         => 'dbs1.example.com',
inclusion_rule          => TRUE,
queue_to_queue          => TRUE);
END;
/

/*

手順11: dbs1.example.comでのhrスキーマのインスタンス化のための準備

strmadminユーザーとしてdbs1.example.comに接続します。

*/

CONNECT strmadmin@dbs1.example.com

/*

hrスキーマをインスタンス化のために準備します。このスキーマ内の表は、dbs5.example.comでインスタンス化されます。この準備は、dbs5.example.comで関連する伝播および適用プロセスのOracle Streamsデータ・ディクショナリに、hrスキーマおよびそのスキーマ内のオブジェクトの情報を含めるために必要です。

関連項目:
『Oracle Streamsレプリケーション管理者ガイド』

*/

BEGIN
DBMS_CAPTURE_ADM.PREPARE_SCHEMA_INSTANTIATION(
schema_name          => 'hr',
supplemental_logging => 'keys');
END;
/

/*

手順12: dbs5.example.comでのdbs1.example.comの表のインスタンス化

この例では、データ・ポンプを使用して次の表のネットワーク・インポートを実行します。

- hr.countries

- hr.departments

- hr.employees

- hr.job_history

- hr.jobs

- hr.locations

- hr.regions

ネットワーク・インポートとは、エクスポート・ダンプ・ファイルを使用せずに、データ・ポンプでdbs1.example.comからこれらの表をインポートすることを意味します。

関連項目:
インポートを実行する方法の詳細は、『Oracle Databaseユーティリティ』を参照してください。

strmadminユーザーとしてdbs5.example.comに接続します。

*/

CONNECT strmadmin@dbs5.example.com

/*

この例では、DBMS_DATAPUMPパッケージを使用して表のインポートを実行します。簡略化するために、どのAPIコールからの例外も捕捉されません。ただし、例外ハンドラを定義し、障害発生時にGET_STATUSをコールしてエラーの詳細情報を取得することをお薦めします。インポートを監視する場合は、インポート・データベースでDBA_DATAPUMP_JOBSデータ・ディクショナリ・ビューを問い合せます。

*/

SET SERVEROUTPUT ON
DECLARE
h1        NUMBER;         -- Data Pump job handle
sscn      NUMBER;         -- Variable to hold current source SCN
job_state VARCHAR2(30);   -- To keep track of job state
js        ku$_JobStatus;  -- The job status from GET_STATUS
sts       ku$_Status;     -- The status object returned by GET_STATUS
job_not_exist    exception;
pragma exception_init(job_not_exist, -31626);
BEGIN
-- Create a (user-named) Data Pump job to do a table-level import.
h1 := DBMS_DATAPUMP.OPEN(
operation   => 'IMPORT',
job_mode    => 'TABLE',
remote_link => 'DBS1.EXAMPLE.COM',
job_name    => 'dp_sing4');
-- A metadata filter is used to specify the schema that owns the tables
-- that will be imported.
DBMS_DATAPUMP.METADATA_FILTER(
handle    => h1,
name      => 'SCHEMA_EXPR',
value     => '=''HR''');
-- Get the current SCN of the source database, and set the FLASHBACK_SCN
-- parameter to this value to ensure consistency between all of the
-- objects included in the import.
sscn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER@dbs1.example.com();
DBMS_DATAPUMP.SET_PARAMETER(
handle => h1,
name   => 'FLASHBACK_SCN',
value  => sscn);
-- Start the job.
DBMS_DATAPUMP.START_JOB(h1);
-- The import job should be running. In the following loop, the job
-- is monitored until it completes.
job_state := 'UNDEFINED';
BEGIN
WHILE (job_state != 'COMPLETED') AND (job_state != 'STOPPED') LOOP
sts:=DBMS_DATAPUMP.GET_STATUS(
handle  => h1,
mask    => DBMS_DATAPUMP.KU$_STATUS_JOB_ERROR +
DBMS_DATAPUMP.KU$_STATUS_JOB_STATUS +
DBMS_DATAPUMP.KU$_STATUS_WIP,
timeout => -1);
js := sts.job_status;
DBMS_LOCK.SLEEP(10);
job_state := js.state;
END LOOP;
-- Gets an exception when job no longer exists
EXCEPTION WHEN job_not_exist THEN
DBMS_OUTPUT.PUT_LINE('Data Pump job has completed');
DBMS_OUTPUT.PUT_LINE('Instantiation SCN: ' ||sscn);
END;
END;
/

/*

手順13: dbs5.example.comでの適用プロセスの起動

Oracle Streams管理者としてdbs5.example.comに接続します。

*/

CONNECT strmadmin@dbs5.example.com

/*

エラーが発生した場合に適用プロセスが無効化されないように、disable_on_errorパラメータをnに設定して、dbs5.example.comで適用プロセスを起動します。

*/

BEGIN
DBMS_APPLY_ADM.SET_PARAMETER(
apply_name  => 'apply',
parameter   => 'disable_on_error',
value       => 'N');
END;
/

BEGIN
DBMS_APPLY_ADM.START_APPLY(
apply_name  => 'apply');
END;
/

/*

手順14: スプール結果のチェック

streams_adddb.outスプール・ファイルをチェックして、このスクリプトの完了後にすべてのアクションが正常に終了していることを確認します。

*/

SET ECHO OFF
SPOOL OFF

/*************************** END OF SCRIPT ******************************/

hr.departments表に対するDML変更

「既存のOracle Streamsレプリケーション環境へのデータベースの追加」で説明した例を完了した後に、dbs1.example.comデータベースのhrスキーマ内の表に対してDML変更およびDDL変更を行うことができます。これらの変更は、dbs5.example.comにレプリケートされます。dbs5.example.comでこれらの表をチェックして、変更がレプリケートされていることを確認できます。

たとえば、次の手順を実行して、dbs1.example.comのhr.departments表に対してDML変更を行います。次に、dbs5.example.comでhr.departments表を問い合せて、変更がレプリケートされていることを確認します。

手順1: hr.departments表に対するDML変更

次の変更を行います。

CONNECT hr@dbs1.example.com
Enter password: password

UPDATE hr.departments SET location_id=2400 WHERE department_id=270;
COMMIT;

手順2: dbs5.example.comでのhr.departments表の問合せ

前述の手順で行った変更が取得、伝播および適用されてから、次の問合せを実行して、dbs1.example.comのhr.departments表に対して行ったUPDATE変更がdbs5.example.comのhr.departments表に適用されていることを確認します。

CONNECT hr@dbs5.example.com
Enter password: password

SELECT location_id FROM hr.departments WHERE department_id=270;

location_idの値が2400と表示されるはずです。

3 n-wayレプリケーションの例

この章では、Oracle Streamsを使用して構成できるn-wayレプリケーション環境の例を説明します。

この章の内容は次のとおりです。

- n-wayレプリケーション例の概要

- 前提条件

- mult1.example.comデータベースでのhrmultスキーマの作成

- キューおよびデータベース・リンクの作成

- n-wayレプリケーションを構成するスクリプトの例

- hrmultスキーマ内の表に対するDML変更およびDDL変更

n-wayレプリケーション例の概要

この例では、Oracle Streamsを使用して、3つのOracle Database間でスキーマのデータをレプリケートする方法について説明します。hrmultスキーマ内の表に対するDML変更とDDL変更が、この環境の全データベースで取得され、この環境の他の各データベースに伝播します。

この種の環境は、n-wayレプリケーション環境と呼ばれます。n-wayレプリケーション環境は、複数のソース・データベースで変更が取得およびレプリケートされる、複数ソース・レプリケーション環境の一種です。

図3-1に、この環境の概要を示します。

図3-1 n-wayレプリケーション環境の例

図3-1に示すように、この例が完了すると、すべてのデータベースにhrmultスキーマが含まれることになります。ただし、この例の開始時には、hrmultスキーマはmult1.example.comにのみ存在します。この例の実行中に、mult2.example.comとmult3.example.comでhrmultスキーマをインスタンス化します。

この例では、Oracle Streamsを使用して次の一連のアクションが実行されます。

1. インスタンス化の後に、各データベースの取得プロセスが、hrmultスキーマ内のすべての表に対するDML変更とDDL変更を取得し、それをローカル・キューにエンキューします。

2. 各データベースの伝播が、これらの変更を環境内の他の全データベースに伝播します。

3. 各データベースの適用プロセスが、環境内の他のデータベースから受信したhrmultスキーマ内の変更を適用します。

この例では、適用プロセスにデフォルトの適用タグを使用してソース・データベースに変更を戻すことは行いません。適用プロセスを作成すると、その適用プロセスによって適用された変更は、デフォルトで'00' (2つのゼロ)というタグが付いたREDOエントリ持ちます。DBMS_STREAMS_ADMパッケージによって作成されたルールにはis_null_tag()='Y'条件がデフォルトで設定されており、REDOエントリのタグがNULLの場合、この条件によって、各取得プロセスは確実にREDOログ・エントリの変更のみを取得するため、これらの変更が再取得されることはありません。

関連項目:

- n-wayレプリケーション環境の詳細は、『Oracle Streamsレプリケーション管理者ガイド』を参照してください。

- タグの詳細は、『Oracle Streamsレプリケーション管理者ガイド』を参照してください。

前提条件

この章の例を開始する前に、前提条件となる次の作業を完了する必要があります。

- Oracle Streams環境内の各データベースで、次の初期化パラメータを指定の値に設定します。

- GLOBAL_NAMES: このパラメータはTRUEに設定する必要があります。データベースのグローバル名がmult1.example.com、mult2.example.comおよびmult3.example.comであることを確認してください。

- COMPATIBLE: このパラメータは10.2.0以上に設定する必要があります。

- PROCESSESおよびSESSIONS初期化パラメータが、この例で使用されるすべてのOracle Streamsクライアントに対して十分に大きい値に設定されていることを確認してください。この例では、各データベースで1つの取得プロセス、2つの伝播および2つの適用プロセスを構成します。

- STREAMS_POOL_SIZE: オプションで、このパラメータを環境内の各データベースの適切な値に設定します。このパラメータでは、Oracle Streamsプールのサイズを指定します。Oracle Streamsプールは、バッファ・キューにメッセージを格納し、パラレル取得およびパラレル適用中の内部通信に使用されます。MEMORY_TARGET、MEMORY_MAX_TARGETまたはSGA_TARGET初期化パラメータを0 (ゼロ)以外の値に設定した場合、Oracle Streamsプールのサイズは自動的に管理されます。

注意:
この例を正しく実行するには、他の初期化パラメータの設定を変更することが必要な場合もあります。

関連項目:
Oracle Streams環境で重要なその他の初期化パラメータについては、『Oracle Streamsレプリケーション管理者ガイド』を参照してください。

- 取得される変更を生成するデータベースは、ARCHIVELOGモードで実行している必要があります。この例では、すべてのデータベースで変更が取得されるため、すべてのデータベースをARCHIVELOGモードで実行する必要があります。

関連項目:
ARCHIVELOGモードでデータベースを実行する方法の詳細は、『Oracle Database管理者ガイド』を参照してください。

- ネットワークとOracle Netを、3つのデータベースすべてが相互に通信できるように構成します。

関連項目:
『Oracle Database Net Services管理者ガイド』

- レプリケーション環境の各データベースでOracle Streams管理者を作成します。この例では、データベースmult1.example.com、mult2.example.comおよびmult3.example.comで作成します。この例では、Oracle Streams管理者のユーザー名がstrmadminであると想定しています。

関連項目:
Oracle Streams管理者を作成する方法は、『Oracle Streamsレプリケーション管理者ガイド』を参照してください。

mult1.example.comデータベースでのhrmultスキーマの作成

この例のために、mult1.example.comデータベースに新しいスキーマhrmultを作成します。n-way環境では、この新しいスキーマがレプリケートされます。

次の手順を実行して、データ・ポンプ・エクスポート/インポートを使用し、hrスキーマのコピーであるhrmultスキーマを作成します。

1. SQL*Plusで、管理ユーザーとしてmult1.example.comデータベースに接続します。
SQL*Plusでデータベースに接続する手順については、『Oracle Database管理者ガイド』を参照してください。

2. エクスポート・ダンプ・ファイルおよびエクスポート・ログ・ファイルを保持するディレクトリ・オブジェクトを作成します。このディレクトリ・オブジェクトは、コンピュータ・システム上のアクセス可能な任意のディレクトリを指すことができます。たとえば、次の文を実行すると、/usr/tmpディレクトリを指すディレクトリ・オブジェクトdp_hrmult_dirが作成されます。

CREATE DIRECTORY dp_hrmult_dir AS '/usr/tmp';

コンピュータ・システム上の適切なディレクトリに置き換えてください。

3. ソース・データベースの現行のシステム変更番号(SCN)を判別します。

SELECT DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER FROM DUAL;

この問合せで戻されるSCN値を、手順5でFLASHBACK_SCNデータ・ポンプ・エクスポート・パラメータに指定します。hrスキーマには表間の外部キー制約が含まれるため、FLASHBACK_SCNエクスポート・パラメータ、または類似のエクスポート・パラメータは、エクスポート中に指定する必要があります。

4. SQL*Plusを終了します。

5. mult1.example.comデータベース・サイトのコマンドラインでデータ・ポンプを使用して、mult1.example.comデータベースのhrスキーマをエクスポートします。手順3で戻されたSCN値をFLASHBACK_SCNパラメータに指定してください。

expdp system SCHEMAS=hr DIRECTORY=dp_hrmult_dir
DUMPFILE=hrmult_schema.dmp FLASHBACK_SCN=flashback_scn_value

6. mult1.example.comデータベース・サイトのコマンドラインでデータ・ポンプを使用して、インポート・ダンプ・ファイルhrmult_schema.dmpをインポートします。

impdp system SCHEMAS=hr DIRECTORY=dp_hrmult_dir
DUMPFILE=hrmult_schema.dmp REMAP_SCHEMA=hr:hrmult

7. SQL*Plusで、管理ユーザーとしてmult1.example.comデータベースに接続します。

8. ALTER USER文を使用して、mult1.example.comデータベースの新しいユーザーhrmultにパスワードを割り当てます。
将来hrmultユーザーとしてログインできるように、割り当てたパスワードを覚えておいてください。

キューおよびデータベース・リンクの作成

この項では、3つのOracle Databaseを含むOracle Streamsレプリケーション環境にキューおよびデータベース・リンクを作成する方法について説明します。この章の残りの項は、この項で構成するキューおよびデータベース・リンクによって異なります。

次の手順を実行して、すべてのデータベースでキューおよびデータベース・リンクを作成します。

1. 出力およびスプール結果の表示

2. mult1.example.comでのANYDATAキューの作成

3. mult1.example.comでのデータベース・リンクの作成

4. mult1.example.comでの最新時刻に基づいた競合解消のための表の準備

5. mult2.example.comでのANYDATAキューの作成

6. mult2.example.comでのデータベース・リンクの作成

7. mult3.example.comでのANYDATAキューの作成

8. mult3.example.comでのデータベース・リンクの作成

9. スプール結果のチェック

注意:
このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。

/************************* BEGINNING OF SCRIPT ******************************

手順1: 出力およびスプール結果の表示

SET ECHO ONを実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。

*/

SET ECHO ON
SPOOL streams_setup_mult.out

/*

手順2: mult1.example.comでのANYDATAキューの作成

Oracle Streams管理者としてmult1.example.comに接続します。

*/

CONNECT strmadmin@mult1.example.com

/*

SET_UP_QUEUEプロシージャを実行して、次のキューを作成します。

- captured_mult1キュー: mult1.example.comデータベースで取得され、他のデータベースに伝播される変更を保持します。

- from_mult2キュー: mult2.example.comデータベースで取得され、mult1.example.comデータベースに伝播されて適用される変更を保持します。

- from_mult3キュー: mult3.example.comデータベースで取得され、mult1.example.comデータベースに伝播されて適用される変更を保持します。

SET_UP_QUEUEプロシージャを実行すると、各キューに次のアクションが実行されます。

- Oracle Streams管理者(strmadmin)が所有し、このユーザーのデフォルトの記憶域を使用するキュー表の作成。

- Oracle Streams管理者(strmadmin)が所有するANYDATAキューの作成。

- キューの起動。

*/

BEGIN
DBMS_STREAMS_ADM.SET_UP_QUEUE(
queue_table  => 'strmadmin.captured_mult1_table',
queue_name   => 'strmadmin.captured_mult1');
END;
/

BEGIN
DBMS_STREAMS_ADM.SET_UP_QUEUE(
queue_table  => 'strmadmin.from_mult2_table',
queue_name   => 'strmadmin.from_mult2');
END;
/

BEGIN
DBMS_STREAMS_ADM.SET_UP_QUEUE(
queue_table  => 'strmadmin.from_mult3_table',
queue_name   => 'strmadmin.from_mult3');
END;
/

/*

手順3: mult1.example.comでのデータベース・リンクの作成

現行データベースから環境内の他のデータベースへのデータベース・リンクを作成します。

*/

ACCEPT password PROMPT 'Enter password for user: ' HIDE

CREATE DATABASE LINK mult2.example.com CONNECT TO strmadmin
IDENTIFIED BY &password USING 'mult2.example.com';

CREATE DATABASE LINK mult3.example.com CONNECT TO strmadmin
IDENTIFIED BY &password USING 'mult3.example.com';

/*

手順4: mult1.example.comでの最新時刻に基づいた競合解消のための表の準備

この例では、トランザクションの最新時刻に基づいて競合解消が行われるようにhrmultスキーマ内の表を構成します。

hrmultユーザーとしてmult1.example.comに接続します。

*/

CONNECT hrmult@mult1.example.com

/*

hrmultスキーマ内の各表にtime列を追加します。

*/

ALTER TABLE hrmult.countries ADD (time TIMESTAMP WITH TIME ZONE);
ALTER TABLE hrmult.departments ADD (time TIMESTAMP WITH TIME ZONE);
ALTER TABLE hrmult.employees ADD (time TIMESTAMP WITH TIME ZONE);
ALTER TABLE hrmult.job_history ADD (time TIMESTAMP WITH TIME ZONE);
ALTER TABLE hrmult.jobs ADD (time TIMESTAMP WITH TIME ZONE);
ALTER TABLE hrmult.locations ADD (time TIMESTAMP WITH TIME ZONE);
ALTER TABLE hrmult.regions ADD (time TIMESTAMP WITH TIME ZONE);

/*

hrmultスキーマ内の各表用のトリガーを作成し、トランザクションによって挿入または更新された各行のトランザクションの時刻を挿入します。

*/

CREATE OR REPLACE TRIGGER hrmult.insert_time_countries
BEFORE
INSERT OR UPDATE ON hrmult.countries FOR EACH ROW
BEGIN
-- Consider time synchronization problems. The previous update to this
-- row might have originated from a site with a clock time ahead of the
-- local clock time.
IF :OLD.TIME IS NULL OR :OLD.TIME < SYSTIMESTAMP THEN
:NEW.TIME := SYSTIMESTAMP;
ELSE
:NEW.TIME := :OLD.TIME + 1 / 86400;
END IF;
END;
/

CREATE OR REPLACE TRIGGER hrmult.insert_time_departments
BEFORE
INSERT OR UPDATE ON hrmult.departments FOR EACH ROW
BEGIN
IF :OLD.TIME IS NULL OR :OLD.TIME < SYSTIMESTAMP THEN
:NEW.TIME := SYSTIMESTAMP;
ELSE
:NEW.TIME := :OLD.TIME + 1 / 86400;
END IF;
END;
/

CREATE OR REPLACE TRIGGER hrmult.insert_time_employees
BEFORE
INSERT OR UPDATE ON hrmult.employees FOR EACH ROW
BEGIN
IF :OLD.TIME IS NULL OR :OLD.TIME < SYSTIMESTAMP THEN
:NEW.TIME := SYSTIMESTAMP;
ELSE
:NEW.TIME := :OLD.TIME + 1 / 86400;
END IF;
END;
/

CREATE OR REPLACE TRIGGER hrmult.insert_time_job_history
BEFORE
INSERT OR UPDATE ON hrmult.job_history FOR EACH ROW
BEGIN
IF :OLD.TIME IS NULL OR :OLD.TIME < SYSTIMESTAMP THEN
:NEW.TIME := SYSTIMESTAMP;
ELSE
:NEW.TIME := :OLD.TIME + 1 / 86400;
END IF;
END;
/

CREATE OR REPLACE TRIGGER hrmult.insert_time_jobs
BEFORE
INSERT OR UPDATE ON hrmult.jobs FOR EACH ROW
BEGIN
IF :OLD.TIME IS NULL OR :OLD.TIME < SYSTIMESTAMP THEN
:NEW.TIME := SYSTIMESTAMP;
ELSE
:NEW.TIME := :OLD.TIME + 1 / 86400;
END IF;
END;
/

CREATE OR REPLACE TRIGGER hrmult.insert_time_locations
BEFORE
INSERT OR UPDATE ON hrmult.locations FOR EACH ROW
BEGIN
IF :OLD.TIME IS NULL OR :OLD.TIME < SYSTIMESTAMP THEN
:NEW.TIME := SYSTIMESTAMP;
ELSE
:NEW.TIME := :OLD.TIME + 1 / 86400;
END IF;
END;
/

CREATE OR REPLACE TRIGGER hrmult.insert_time_regions
BEFORE
INSERT OR UPDATE ON hrmult.regions FOR EACH ROW
BEGIN
IF :OLD.TIME IS NULL OR :OLD.TIME < SYSTIMESTAMP THEN
:NEW.TIME := SYSTIMESTAMP;
ELSE
:NEW.TIME := :OLD.TIME + 1 / 86400;
END IF;
END;
/

/*

手順5: mult2.example.comでのANYDATAキューの作成

Oracle Streams管理者としてmult2.example.comに接続します。

*/

CONNECT strmadmin@mult2.example.com

/*

SET_UP_QUEUEプロシージャを実行して、次のキューを作成します。

- captured_mult2キュー: mult2.example.comデータベースで取得され、他のデータベースに伝播される変更を保持します。

- from_mult1キュー: mult1.example.comデータベースで取得され、mult2.example.comデータベースに伝播されて適用される変更を保持します。

- from_mult3キュー: mult3.example.comデータベースで取得され、mult2.example.comデータベースに伝播されて適用される変更を保持します。

SET_UP_QUEUEプロシージャを実行すると、各キューに次のアクションが実行されます。

- Oracle Streams管理者(strmadmin)が所有し、このユーザーのデフォルトの記憶域を使用するキュー表の作成。

- Oracle Streams管理者(strmadmin)が所有するANYDATAキューの作成。

- キューの起動。

*/

BEGIN
DBMS_STREAMS_ADM.SET_UP_QUEUE(
queue_table  => 'strmadmin.captured_mult2_table',
queue_name   => 'strmadmin.captured_mult2');
END;
/

BEGIN
DBMS_STREAMS_ADM.SET_UP_QUEUE(
queue_table  => 'strmadmin.from_mult1_table',
queue_name   => 'strmadmin.from_mult1');
END;
/

BEGIN
DBMS_STREAMS_ADM.SET_UP_QUEUE(
queue_table  => 'strmadmin.from_mult3_table',
queue_name   => 'strmadmin.from_mult3');
END;
/

/*

手順6: mult2.example.comでのデータベース・リンクの作成

現行データベースから環境内の他のデータベースへのデータベース・リンクを作成します。

*/

CREATE DATABASE LINK mult1.example.com CONNECT TO strmadmin
IDENTIFIED BY &password USING 'mult1.example.com';

CREATE DATABASE LINK mult3.example.com CONNECT TO strmadmin
IDENTIFIED BY &password USING 'mult3.example.com';

/*

手順7: mult3.example.comでのANYDATAキューの作成

Oracle Streams管理者としてmult3.example.comに接続します。

*/

CONNECT strmadmin@mult3.example.com

/*

SET_UP_QUEUEプロシージャを実行して、次のキューを作成します。

- captured_mult3キュー: mult3.example.comデータベースで取得され、他のデータベースに伝播される変更を保持します。

- from_mult1キュー: mult1.example.comデータベースで取得され、mult3.example.comデータベースに伝播されて適用される変更を保持します。

- from_mult2キュー: mult2.example.comデータベースで取得され、mult3.example.comデータベースに伝播されて適用される変更を保持します。

SET_UP_QUEUEプロシージャを実行すると、各キューに次のアクションが実行されます。

- Oracle Streams管理者(strmadmin)が所有し、このユーザーのデフォルトの記憶域を使用するキュー表の作成。

- Oracle Streams管理者(strmadmin)が所有するANYDATAキューの作成。

- キューの起動。

*/

BEGIN
DBMS_STREAMS_ADM.SET_UP_QUEUE(
queue_table  => 'strmadmin.captured_mult3_table',
queue_name   => 'strmadmin.captured_mult3');
END;
/

BEGIN
DBMS_STREAMS_ADM.SET_UP_QUEUE(
queue_table  => 'strmadmin.from_mult1_table',
queue_name   => 'strmadmin.from_mult1');
END;
/

BEGIN
DBMS_STREAMS_ADM.SET_UP_QUEUE(
queue_table  => 'strmadmin.from_mult2_table',
queue_name   => 'strmadmin.from_mult2');
END;
/

/*

手順8: mult3.example.comでのデータベース・リンクの作成

現行データベースから環境内の他のデータベースへのデータベース・リンクを作成します。

*/

CREATE DATABASE LINK mult1.example.com CONNECT TO strmadmin
IDENTIFIED BY &password USING 'mult1.example.com';

CREATE DATABASE LINK mult2.example.com CONNECT TO strmadmin
IDENTIFIED BY &password USING 'mult2.example.com';

/*

手順9: スプール結果のチェック

streams_setup_mult.outスプール・ファイルをチェックして、このスクリプトの完了後にすべてのアクションが正常に終了していることを確認します。

*/

SET ECHO OFF
SPOOL OFF

/*************************** END OF SCRIPT ******************************/

n-wayレプリケーションを構成するスクリプトの例

次の手順を実行して、Oracle Streams n-wayレプリケーション環境を構成します。

1. 出力およびスプール結果の表示

2. mult1.example.comでのサプリメンタル・ロギングの指定

3. mult1.example.comでの取得プロセスの作成

4. mult1.example.comでの各ソース・データベース用の1つの適用プロセスの作成

5. mult1.example.comでの最新時刻に基づいた競合解消の構成

6. mult1.example.comでの伝播の構成

7. mult2.example.comでの取得プロセスの作成

8. 他のデータベースでのmult2.example.comに対するインスタンス化SCNの設定

9. mult2.example.comでの各ソース・データベース用の1つの適用プロセスの作成

10. mult2.example.comでの伝播の構成

11. mult3.example.comでの取得プロセスの作成

12. 他のデータベースでのmult3.example.comに対するインスタンス化SCNの設定

13. mult3.example.comでの各ソース・データベース用の1つの適用プロセスの作成

14. mult3.example.comでの伝播の構成

15. mult2.example.comでのhrmultスキーマのインスタンス化

16. mult3.example.comでのhrmultスキーマのインスタンス化

17. mult2.example.comでの最新時刻に基づいた競合解消の構成

18. mult2.example.comでの適用プロセスの起動

19. mult3.example.comでの最新時刻に基づいた競合解消の構成

20. mult3.example.comでの適用プロセスの起動

21. mult1.example.comでの適用プロセスの起動

22. mult1.example.comでの取得プロセスの起動

23. mult2.example.comでの取得プロセスの起動

24. mult3.example.comでの取得プロセスの起動

25. スプール結果のチェック

注意:
このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。

/************************* BEGINNING OF SCRIPT ******************************

手順1: 出力およびスプール結果の表示

SET ECHO ONを実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。

*/

SET ECHO ON
SPOOL streams_mult.out

/*

手順2: mult1.example.comでのサプリメンタル・ロギングの指定

strmadminユーザーとしてmult1.example.comに接続します。

*/

CONNECT strmadmin@mult1.example.com

/*

「mult1.example.comでの最新時刻に基づいた競合解消の構成」の指定に従って、各表の主キーおよび各表の列リストを含む無条件のサプリメンタル・ログ・グループを指定します。各表の列リストには、各表の主キー以外のすべての列が含まれているため、この手順では、表のすべての列を含む各表のサプリメンタル・ログ・グループを作成します。

注意:

- 便宜上、この例では、単一の無条件ログ・グループに各表の主キー列および更新の競合解消に使用される列を含めます。各表の主キー列を無条件ログ・グループに含め、更新の競合解消に使用される列を条件付きログ・グループに含めることができます。

- この例では、mult2.example.comおよびmult3.example.comで、サプリメンタル・ロギングを明示的に指定する必要はありません。この例の後半で、データ・ポンプを使用してこれらのデータベースでhrmultスキーマ内の表をインスタンス化する際に、mult1.example.comでのサプリメンタル・ロギングの指定がmult2.example.comおよびmult3.example.comに保持されます。

関連項目:
『Oracle Streamsレプリケーション管理者ガイド』

*/

ALTER TABLE hrmult.countries ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

ALTER TABLE hrmult.departments ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

ALTER TABLE hrmult.employees ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

ALTER TABLE hrmult.jobs ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

ALTER TABLE hrmult.job_history ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

ALTER TABLE hrmult.locations ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

ALTER TABLE hrmult.regions ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

/*

手順3: mult1.example.comでの取得プロセスの作成

mult1.example.comでhrmultスキーマ全体に対する変更を取得するように取得プロセスを作成します。また、この手順では、mult1.example.comでhrmultスキーマをインスタンス化のために準備します。この手順の実行後、ユーザーはmult1.example.comでhrmultスキーマ内の表を変更できます。

*/

BEGIN
DBMS_STREAMS_ADM.ADD_SCHEMA_RULES(
schema_name    => 'hrmult',
streams_type   => 'capture',
streams_name   => 'capture_hrmult',
queue_name     => 'strmadmin.captured_mult1',
include_dml    => TRUE,
include_ddl    => TRUE,
inclusion_rule => TRUE);
END;
/

/*

手順4: mult1.example.comでの各ソース・データベース用の1つの適用プロセスの作成

mult2.example.comのhrmultスキーマに変更を適用するようにmult1.example.comを構成します。

*/

BEGIN
DBMS_STREAMS_ADM.ADD_SCHEMA_RULES(
schema_name     => 'hrmult',
streams_type    => 'apply',
streams_name    => 'apply_from_mult2',
queue_name      => 'strmadmin.from_mult2',
include_dml     => TRUE,
include_ddl     => TRUE,
source_database => 'mult2.example.com',
inclusion_rule  => TRUE);
END;
/

/*

mult3.example.comのhrmultスキーマに変更を適用するようにmult1.example.comを構成します。

*/

BEGIN
DBMS_STREAMS_ADM.ADD_SCHEMA_RULES(
schema_name     => 'hrmult',
streams_type    => 'apply',
streams_name    => 'apply_from_mult3',
queue_name      => 'strmadmin.from_mult3',
include_dml     => TRUE,
include_ddl     => TRUE,
source_database => 'mult3.example.com',
inclusion_rule  => TRUE);
END;
/

/*

手順5: mult1.example.comでの最新時刻に基づいた競合解消の構成

hrmultスキーマ内の各表に更新競合ハンドラを指定します。各表で、MAXIMUM競合ハンドラの解消列としてtime列を指定します。更新の競合が発生すると、このような競合ハンドラは最新(または最大)時刻のトランザクションを適用し、それより前の(または小さい)時刻のトランザクションを廃棄します。この例では、主キー値が更新されないと想定しているため、列リストには主キーを除く各表のすべての列が含まれます。

*/

DECLARE
cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
cols(1) := 'country_name';
cols(2) := 'region_id';
cols(3) := 'time';
DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
object_name           =>  'hrmult.countries',
method_name           =>  'MAXIMUM',
resolution_column     =>  'time',
column_list           =>  cols);
END;
/

DECLARE
cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
cols(1) := 'department_name';
cols(2) := 'manager_id';
cols(3) := 'location_id';
cols(4) := 'time';
DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
object_name           =>  'hrmult.departments',
method_name           =>  'MAXIMUM',
resolution_column     =>  'time',
column_list           =>  cols);
END;
/

DECLARE
cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
cols(1)  := 'first_name';
cols(2)  := 'last_name';
cols(3)  := 'email';
cols(4)  := 'phone_number';
cols(5)  := 'hire_date';
cols(6)  := 'job_id';
cols(7)  := 'salary';
cols(8)  := 'commission_pct';
cols(9)  := 'manager_id';
cols(10) := 'department_id';
cols(11) := 'time';
DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
object_name           =>  'hrmult.employees',
method_name           =>  'MAXIMUM',
resolution_column     =>  'time',
column_list           =>  cols);
END;
/

DECLARE
cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
cols(1) := 'job_title';
cols(2) := 'min_salary';
cols(3) := 'max_salary';
cols(4) := 'time';
DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
object_name           =>  'hrmult.jobs',
method_name           =>  'MAXIMUM',
resolution_column     =>  'time',
column_list           =>  cols);
END;
/

DECLARE
cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
cols(1) := 'employee_id';
cols(2) := 'start_date';
cols(3) := 'end_date';
cols(4) := 'job_id';
cols(5) := 'department_id';
cols(6) := 'time';
DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
object_name           =>  'hrmult.job_history',
method_name           =>  'MAXIMUM',
resolution_column     =>  'time',
column_list           =>  cols);
END;
/

DECLARE
cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
cols(1) := 'street_address';
cols(2) := 'postal_code';
cols(3) := 'city';
cols(4) := 'state_province';
cols(5) := 'country_id';
cols(6) := 'time';
DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
object_name           =>  'hrmult.locations',
method_name           =>  'MAXIMUM',
resolution_column     =>  'time',
column_list           =>  cols);
END;
/

DECLARE
cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
cols(1) := 'region_name';
cols(2) := 'time';
DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
object_name           =>  'hrmult.regions',
method_name           =>  'MAXIMUM',
resolution_column     =>  'time',
column_list           =>  cols);
END;
/

/*

手順6: mult1.example.comでの伝播の構成

mult1.example.comのキューからmult2.example.comのキューへのhrmultスキーマ内のDML変更およびDDL変更の伝播を構成およびスケジュールします。

*/

BEGIN
DBMS_STREAMS_ADM.ADD_SCHEMA_PROPAGATION_RULES(
schema_name               => 'hrmult',
streams_name              => 'mult1_to_mult2',
source_queue_name         => 'strmadmin.captured_mult1',
destination_queue_name    => 'strmadmin.from_mult1@mult2.example.com',
include_dml               => TRUE,
include_ddl               => TRUE,
source_database           => 'mult1.example.com',
inclusion_rule            => TRUE,
queue_to_queue            => TRUE);
END;
/

/*

mult1.example.comのキューからmult3.example.comのキューへのhrmultスキーマ内のDML変更およびDDL変更の伝播を構成およびスケジュールします。

*/

BEGIN
DBMS_STREAMS_ADM.ADD_SCHEMA_PROPAGATION_RULES(
schema_name               => 'hrmult',
streams_name              => 'mult1_to_mult3',
source_queue_name         => 'strmadmin.captured_mult1',
destination_queue_name    => 'strmadmin.from_mult1@mult3.example.com',
include_dml               => TRUE,
include_ddl               => TRUE,
source_database           => 'mult1.example.com',
inclusion_rule            => TRUE,
queue_to_queue            => TRUE);
END;
/

/*

手順7: mult2.example.comでの取得プロセスの作成

strmadminユーザーとしてmult2.example.comに接続します。

*/

CONNECT strmadmin@mult2.example.com

/*

mult2.example.comでhrmultスキーマ全体に対する変更を取得するように取得プロセスを作成します。また、この手順では、mult2.example.comでhrmultスキーマをインスタンス化のために準備します。

*/

BEGIN
DBMS_STREAMS_ADM.ADD_SCHEMA_RULES(
schema_name    => 'hrmult',
streams_type   => 'capture',
streams_name   => 'capture_hrmult',
queue_name     => 'strmadmin.captured_mult2',
include_dml    => TRUE,
include_ddl    => TRUE,
inclusion_rule => TRUE);
END;
/

/*

手順8: 他のデータベースでのmult2.example.comに対するインスタンス化SCNの設定

この例では、すべてのデータベースにhrmultスキーマがすでに存在します。手順16でmult2.example.comおよびmult3.example.comでインスタンス化されるまで、スキーマ内の表はmult1.example.comにのみ存在します。インスタンス化は、mult1.example.comからの表のインポートを使用して実行されます。これらのインポート操作によって、mult2.example.comおよびmult3.example.comのmult1.example.comでのスキーマのインスタンス化SCNが自動的に設定されます。

ただし、mult2.example.comおよびmult3.example.comのインスタンス化SCNは、環境内の他のサイトでは自動的に設定されません。この手順では、mult1.example.comおよびmult3.example.comでmult2.example.comのスキーマのインスタンス化SCNを手動で設定します。mult2.example.comでの現行のSCNは、mult2.example.comでDBMS_FLASHBACKパッケージのGET_SYSTEM_CHANGE_NUMBERファンクションを使用して取得できます。このSCNは、mult1.example.comおよびmult3.example.comでDBMS_APPLY_ADMパッケージのSET_SCHEMA_INSTANTIATION_SCNプロシージャを実行するために使用されます。

SET_SCHEMA_INSTANTIATION_SCNプロシージャを使用すると、適用プロセスで無視されるスキーマのDDL LCRと、適用プロセスで適用されるスキーマのDDL LCRを制御できます。ソース・データベースからのスキーマ内のデータベース・オブジェクトに関するDDL LCRのコミットSCNが、一部の接続先データベースでそのデータベース・オブジェクトのインスタンス化SCN以下であれば、接続先データベースの適用プロセスではDDL LCRが無視されます。それ以外の場合は、適用プロセスによってDDL LCRが適用されます。

SET_SCHEMA_INSTANTIATION_SCNプロシージャは、mult2.example.comで表がインスタンス化される前に実行し、ローカルの取得プロセスがすでに構成されているため、インスタンス化後の表ごとにSET_TABLE_INSTANTIATION_SCNプロシージャを実行する必要はありません。この例では、mult1.example.comとmult3.example.comの両方の適用プロセスは、この手順で取得したSCNの後にコミットされたSCNを持つhrmultスキーマ内の表にトランザクションを適用します。

注意:

- 存在しないスキーマをインスタンス化する場合、スキーマのインスタンス化SCNのかわりに、グローバルのインスタンス化SCNを設定できます。

- インスタンス化SCNを設定する前に表がインスタンス化された場合は、スキーマ内の各表に対してスキーマのインスタンス化SCNおよびインスタンス化SCNを設定する必要があります。

*/

DECLARE
iscn  NUMBER;         -- Variable to hold instantiation SCN value
BEGIN
iscn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER();
DBMS_APPLY_ADM.SET_SCHEMA_INSTANTIATION_SCN@MULT1.EXAMPLE.COM(
source_schema_name    => 'hrmult',
source_database_name  => 'mult2.example.com',
instantiation_scn     => iscn);
DBMS_APPLY_ADM.SET_SCHEMA_INSTANTIATION_SCN@MULT3.EXAMPLE.COM(
source_schema_name    => 'hrmult',
source_database_name  => 'mult2.example.com',
instantiation_scn     => iscn);
END;
/

/*

手順9: mult2.example.comでの各ソース・データベース用の1つの適用プロセスの作成

mult1.example.comのhrmultスキーマに変更を適用するようにmult2.example.comを構成します。

*/

BEGIN
DBMS_STREAMS_ADM.ADD_SCHEMA_RULES(
schema_name     => 'hrmult',
streams_type    => 'apply',
streams_name    => 'apply_from_mult1',
queue_name      => 'strmadmin.from_mult1',
include_dml     => TRUE,
include_ddl     => TRUE,
source_database => 'mult1.example.com',
inclusion_rule  => TRUE);
END;
/

/*

mult3.example.comのhrmultスキーマに変更を適用するようにmult2.example.comを構成します。

*/

BEGIN
DBMS_STREAMS_ADM.ADD_SCHEMA_RULES(
schema_name     => 'hrmult',
streams_type    => 'apply',
streams_name    => 'apply_from_mult3',
queue_name      => 'strmadmin.from_mult3',
include_dml     => TRUE,
include_ddl     => TRUE,
source_database => 'mult3.example.com',
inclusion_rule  => TRUE);
END;
/

/*

手順10: mult2.example.comでの伝播の構成

mult2.example.comのキューからmult1.example.comのキューへのhrmultスキーマ内のDML変更およびDDL変更の伝播を構成およびスケジュールします。

*/

BEGIN
DBMS_STREAMS_ADM.ADD_SCHEMA_PROPAGATION_RULES(
schema_name             => 'hrmult',
streams_name            => 'mult2_to_mult1',
source_queue_name       => 'strmadmin.captured_mult2',
destination_queue_name  => 'strmadmin.from_mult2@mult1.example.com',
include_dml             => TRUE,
include_ddl             => TRUE,
source_database         => 'mult2.example.com',
inclusion_rule          => TRUE,
queue_to_queue          => TRUE);
END;
/

/*

mult2.example.comのキューからmult3.example.comのキューへのhrmultスキーマ内のDML変更およびDDL変更の伝播を構成およびスケジュールします。

*/

BEGIN
DBMS_STREAMS_ADM.ADD_SCHEMA_PROPAGATION_RULES(
schema_name             => 'hrmult',
streams_name            => 'mult2_to_mult3',
source_queue_name       => 'strmadmin.captured_mult2',
destination_queue_name  => 'strmadmin.from_mult2@mult3.example.com',
include_dml             => TRUE,
include_ddl             => TRUE,
source_database         => 'mult2.example.com',
inclusion_rule          => TRUE,
queue_to_queue          => TRUE);
END;
/

/*

手順11: mult3.example.comでの取得プロセスの作成

strmadminユーザーとしてmult3.example.comに接続します。

*/

CONNECT strmadmin@mult3.example.com

/*

mult3.example.comでhrmultスキーマ全体に対する変更を取得するように取得プロセスを作成します。また、この手順では、mult3.example.comでhrmultスキーマをインスタンス化のために準備します。

*/

BEGIN
DBMS_STREAMS_ADM.ADD_SCHEMA_RULES(
schema_name    => 'hrmult',
streams_type   => 'capture',
streams_name   => 'capture_hrmult',
queue_name     => 'strmadmin.captured_mult3',
include_dml    => TRUE,
include_ddl    => TRUE,
inclusion_rule => TRUE);
END;
/

/*

手順12: 他のデータベースでのmult3.example.comに対するインスタンス化SCNの設定

この例では、すべてのデータベースにhrmultスキーマがすでに存在します。手順16でmult2.example.comおよびmult3.example.comでインスタンス化されるまで、スキーマ内の表はmult1.example.comにのみ存在します。インスタンス化は、mult1.example.comからの表のインポートを使用して実行されます。これらのインポート操作によって、mult2.example.comおよびmult3.example.comのmult1.example.comでのスキーマのインスタンス化SCNが自動的に設定されます。

ただし、mult2.example.comおよびmult3.example.comのインスタンス化SCNは、環境内の他のサイトでは自動的に設定されません。この手順では、mult1.example.comおよびmult2.example.comでmult3.example.comのスキーマのインスタンス化SCNを手動で設定します。mult3.example.comでの現行のSCNは、mult3.example.comでDBMS_FLASHBACKパッケージのGET_SYSTEM_CHANGE_NUMBERファンクションを使用して取得できます。このSCNは、mult1.example.comおよびmult2.example.comでDBMS_APPLY_ADMパッケージのSET_SCHEMA_INSTANTIATION_SCNプロシージャを実行するために使用されます。

SET_SCHEMA_INSTANTIATION_SCNプロシージャを使用すると、適用プロセスで無視されるスキーマのDDL LCRと、適用プロセスで適用されるスキーマのDDL LCRを制御できます。ソース・データベースからのスキーマ内のデータベース・オブジェクトに関するDDL LCRのコミットSCNが、一部の接続先データベースでそのデータベース・オブジェクトのインスタンス化SCN以下であれば、接続先データベースの適用プロセスではDDL LCRが無視されます。それ以外の場合は、適用プロセスによってDDL LCRが適用されます。

SET_SCHEMA_INSTANTIATION_SCNプロシージャは、mult3.example.comで表がインスタンス化される前に実行し、ローカルの取得プロセスがすでに構成されているため、インスタンス化後の表ごとにSET_TABLE_INSTANTIATION_SCNプロシージャを実行する必要はありません。この例では、mult1.example.comとmult2.example.comの両方の適用プロセスは、この手順で取得したSCNの後にコミットされたSCNを持つhrmultスキーマ内の表にトランザクションを適用します。

注意:

- 存在しないスキーマをインスタンス化する場合、スキーマのインスタンス化SCNのかわりに、グローバルのインスタンス化SCNを設定できます。

- インスタンス化SCNを設定する前に表がインスタンス化された場合は、スキーマ内の各表に対してスキーマのインスタンス化SCNおよびインスタンス化SCNを設定する必要があります。

*/

DECLARE
iscn  NUMBER;         -- Variable to hold instantiation SCN value
BEGIN
iscn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER();
DBMS_APPLY_ADM.SET_SCHEMA_INSTANTIATION_SCN@MULT1.EXAMPLE.COM(
source_schema_name    => 'hrmult',
source_database_name  => 'mult3.example.com',
instantiation_scn     => iscn);
DBMS_APPLY_ADM.SET_SCHEMA_INSTANTIATION_SCN@MULT2.EXAMPLE.COM(
source_schema_name    => 'hrmult',
source_database_name  => 'mult3.example.com',
instantiation_scn     => iscn);
END;
/

/*

手順13: mult3.example.comでの各ソース・データベース用の1つの適用プロセスの作成

mult1.example.comのhrmultスキーマに変更を適用するようにmult3.example.comを構成します。

*/

BEGIN
DBMS_STREAMS_ADM.ADD_SCHEMA_RULES(
schema_name     => 'hrmult',
streams_type    => 'apply',
streams_name    => 'apply_from_mult1',
queue_name      => 'strmadmin.from_mult1',
include_dml     => TRUE,
include_ddl     => TRUE,
source_database => 'mult1.example.com',
inclusion_rule  => TRUE);
END;
/

/*

mult2.example.comのhrmultスキーマに変更を適用するようにmult3.example.comを構成します。

*/

BEGIN
DBMS_STREAMS_ADM.ADD_SCHEMA_RULES(
schema_name     => 'hrmult',
streams_type    => 'apply',
streams_name    => 'apply_from_mult2',
queue_name      => 'strmadmin.from_mult2',
include_dml     => TRUE,
include_ddl     => TRUE,
source_database => 'mult2.example.com',
inclusion_rule  => TRUE);
END;
/

/*

手順14: mult3.example.comでの伝播の構成

mult3.example.comのキューからmult1.example.comのキューへのhrmultスキーマ内のDML変更およびDDL変更の伝播を構成およびスケジュールします。

*/

BEGIN
DBMS_STREAMS_ADM.ADD_SCHEMA_PROPAGATION_RULES(
schema_name             => 'hrmult',
streams_name            => 'mult3_to_mult1',
source_queue_name       => 'strmadmin.captured_mult3',
destination_queue_name  => 'strmadmin.from_mult3@mult1.example.com',
include_dml             => TRUE,
include_ddl             => TRUE,
source_database         => 'mult3.example.com',
inclusion_rule          => TRUE,
queue_to_queue          => TRUE);
END;
/

/*

mult3.example.comのキューからmult2.example.comのキューへのhrmultスキーマ内のDML変更およびDDL変更の伝播を構成およびスケジュールします。

*/

BEGIN
DBMS_STREAMS_ADM.ADD_SCHEMA_PROPAGATION_RULES(
schema_name             => 'hrmult',
streams_name            => 'mult3_to_mult2',
source_queue_name       => 'strmadmin.captured_mult3',
destination_queue_name  => 'strmadmin.from_mult3@mult2.example.com',
include_dml             => TRUE,
include_ddl             => TRUE,
source_database         => 'mult3.example.com',
inclusion_rule          => TRUE,
queue_to_queue          => TRUE);
END;
/

/*

手順15: mult2.example.comでのhrmultスキーマのインスタンス化

この例では、データ・ポンプを使用してmult1.example.comからmult2.example.comへのhrmultスキーマのネットワーク・インポートを実行します。ネットワーク・インポートとは、エクスポート・ダンプ・ファイルを使用せずに、データ・ポンプでmult1.example.comからスキーマのデータベース・オブジェクトをインポートすることを意味します。

関連項目:
インポートを実行する方法の詳細は、『Oracle Databaseユーティリティ』を参照してください。

strmadminユーザーとしてmult2.example.comに接続します。

*/

CONNECT strmadmin@mult2.example.com

/*

この例では、DBMS_DATAPUMPパッケージを使用してスキーマ・レベルのインポートを実行します。簡略化するために、どのAPIコールからの例外も捕捉されません。ただし、例外ハンドラを定義し、障害発生時にGET_STATUSをコールしてエラーの詳細情報を取得することをお薦めします。インポートを監視する場合は、インポート・データベースでDBA_DATAPUMP_JOBSデータ・ディクショナリ・ビューを問い合せます。

*/

SET SERVEROUTPUT ON
DECLARE
h1                 NUMBER;         -- Data Pump job handle
mult2_instantscn   NUMBER;         -- Variable to hold current source SCN
job_state          VARCHAR2(30);   -- To keep track of job state
js                 ku$_JobStatus;  -- The job status from GET_STATUS
sts                ku$_Status;     -- The status object returned by GET_STATUS
job_not_exist    exception;
pragma exception_init(job_not_exist, -31626);
BEGIN
-- Create a (user-named) Data Pump job to do a schema-level import.
h1 := DBMS_DATAPUMP.OPEN(
operation   => 'IMPORT',
job_mode    => 'SCHEMA',
remote_link => 'MULT1.EXAMPLE.COM',
job_name    => 'dp_mult2');
-- A metadata filter is used to specify the schema that owns the tables
-- that will be imported.
DBMS_DATAPUMP.METADATA_FILTER(
handle    => h1,
name      => 'SCHEMA_EXPR',
value     => '=''HRMULT''');
-- Get the current SCN of the source database, and set the FLASHBACK_SCN
-- parameter to this value to ensure consistency between all of the
-- objects in the schema.
mult2_instantscn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER@mult1.example.com();
DBMS_DATAPUMP.SET_PARAMETER(
handle => h1,
name   => 'FLASHBACK_SCN',
value  => mult2_instantscn);
-- Start the job.
DBMS_DATAPUMP.START_JOB(h1);
-- The import job should be running. In the following loop, the job
-- is monitored until it completes.
job_state := 'UNDEFINED';
BEGIN
WHILE (job_state != 'COMPLETED') AND (job_state != 'STOPPED') LOOP
sts:=DBMS_DATAPUMP.GET_STATUS(
handle  => h1,
mask    => DBMS_DATAPUMP.KU$_STATUS_JOB_ERROR +
DBMS_DATAPUMP.KU$_STATUS_JOB_STATUS +
DBMS_DATAPUMP.KU$_STATUS_WIP,
timeout => -1);
js := sts.job_status;
DBMS_LOCK.SLEEP(10);
job_state := js.state;
END LOOP;
-- Gets an exception when job no longer exists
EXCEPTION WHEN job_not_exist THEN
DBMS_OUTPUT.PUT_LINE('Data Pump job has completed');
DBMS_OUTPUT.PUT_LINE('Instantiation SCN: ' ||mult2_instantscn);
END;
END;
/

/*

手順16: mult3.example.comでのhrmultスキーマのインスタンス化

この例では、データ・ポンプを使用してmult1.example.comからmult3.example.comへのhrmultスキーマのネットワーク・インポートを実行します。ネットワーク・インポートとは、エクスポート・ダンプ・ファイルを使用せずに、データ・ポンプでmult1.example.comからスキーマのデータベース・オブジェクトをインポートすることを意味します。

関連項目:
インポートを実行する方法の詳細は、『Oracle Databaseユーティリティ』を参照してください。

strmadminユーザーとしてmult3.example.comに接続します。

*/

CONNECT strmadmin@mult3.example.com

/*

この例では、DBMS_DATAPUMPパッケージを使用して表のインポートを実行します。簡略化するために、どのAPIコールからの例外も捕捉されません。ただし、例外ハンドラを定義し、障害発生時にGET_STATUSをコールしてエラーの詳細情報を取得することをお薦めします。インポートを監視する場合は、インポート・データベースでDBA_DATAPUMP_JOBSデータ・ディクショナリ・ビューを問い合せます。

*/

SET SERVEROUTPUT ON
DECLARE
h1                 NUMBER;         -- Data Pump job handle
mult3_instantscn   NUMBER;         -- Variable to hold current source SCN
job_state          VARCHAR2(30);   -- To keep track of job state
js                 ku$_JobStatus;  -- The job status from GET_STATUS
sts                ku$_Status;     -- The status object returned by GET_STATUS
job_not_exist    exception;
pragma exception_init(job_not_exist, -31626);
BEGIN
-- Create a (user-named) Data Pump job to do a schema-level import.
h1 := DBMS_DATAPUMP.OPEN(
operation   => 'IMPORT',
job_mode    => 'SCHEMA',
remote_link => 'MULT1.EXAMPLE.COM',
job_name    => 'dp_mult3');
-- A metadata filter is used to specify the schema that owns the tables
-- that will be imported.
DBMS_DATAPUMP.METADATA_FILTER(
handle    => h1,
name      => 'SCHEMA_EXPR',
value     => '=''HRMULT''');
-- Get the current SCN of the source database, and set the FLASHBACK_SCN
-- parameter to this value to ensure consistency between all of the
-- objects in the schema.
mult3_instantscn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER@mult1.example.com();
DBMS_DATAPUMP.SET_PARAMETER(
handle => h1,
name   => 'FLASHBACK_SCN',
value  => mult3_instantscn);
-- Start the job.
DBMS_DATAPUMP.START_JOB(h1);
-- The import job should be running. In the following loop, the job
-- is monitored until it completes.
job_state := 'UNDEFINED';
BEGIN
WHILE (job_state != 'COMPLETED') AND (job_state != 'STOPPED') LOOP
sts:=DBMS_DATAPUMP.GET_STATUS(
handle  => h1,
mask    => DBMS_DATAPUMP.KU$_STATUS_JOB_ERROR +
DBMS_DATAPUMP.KU$_STATUS_JOB_STATUS +
DBMS_DATAPUMP.KU$_STATUS_WIP,
timeout => -1);
js := sts.job_status;
DBMS_LOCK.SLEEP(10);
job_state := js.state;
END LOOP;
-- Gets an exception when job no longer exists
EXCEPTION WHEN job_not_exist THEN
DBMS_OUTPUT.PUT_LINE('Data Pump job has completed');
DBMS_OUTPUT.PUT_LINE('Instantiation SCN: ' ||mult3_instantscn);
END;
END;
/

/*

手順17: mult2.example.comでの最新時刻に基づいた競合解消の構成

strmadminユーザーとしてmult2.example.comに接続します。

*/

CONNECT strmadmin@mult2.example.com

/*

hrmultスキーマ内の各表に更新競合ハンドラを指定します。各表で、MAXIMUM競合ハンドラの解消列としてtime列を指定します。更新の競合が発生すると、このような競合ハンドラは最新(または最大)時刻のトランザクションを適用し、それより前の(または小さい)時刻のトランザクションを廃棄します。

*/

DECLARE
cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
cols(1) := 'country_name';
cols(2) := 'region_id';
cols(3) := 'time';
DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
object_name           =>  'hrmult.countries',
method_name           =>  'MAXIMUM',
resolution_column     =>  'time',
column_list           =>  cols);
END;
/

DECLARE
cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
cols(1) := 'department_name';
cols(2) := 'manager_id';
cols(3) := 'location_id';
cols(4) := 'time';
DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
object_name           =>  'hrmult.departments',
method_name           =>  'MAXIMUM',
resolution_column     =>  'time',
column_list           =>  cols);
END;
/

DECLARE
cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
cols(1)  := 'first_name';
cols(2)  := 'last_name';
cols(3)  := 'email';
cols(4)  := 'phone_number';
cols(5)  := 'hire_date';
cols(6)  := 'job_id';
cols(7)  := 'salary';
cols(8)  := 'commission_pct';
cols(9)  := 'manager_id';
cols(10) := 'department_id';
cols(11) := 'time';
DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
object_name           =>  'hrmult.employees',
method_name           =>  'MAXIMUM',
resolution_column     =>  'time',
column_list           =>  cols);
END;
/

DECLARE
cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
cols(1) := 'job_title';
cols(2) := 'min_salary';
cols(3) := 'max_salary';
cols(4) := 'time';
DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
object_name           =>  'hrmult.jobs',
method_name           =>  'MAXIMUM',
resolution_column     =>  'time',
column_list           =>  cols);
END;
/

DECLARE
cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
cols(1) := 'employee_id';
cols(2) := 'start_date';
cols(3) := 'end_date';
cols(4) := 'job_id';
cols(5) := 'department_id';
cols(6) := 'time';
DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
object_name           =>  'hrmult.job_history',
method_name           =>  'MAXIMUM',
resolution_column     =>  'time',
column_list           =>  cols);
END;
/

DECLARE
cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
cols(1) := 'street_address';
cols(2) := 'postal_code';
cols(3) := 'city';
cols(4) := 'state_province';
cols(5) := 'country_id';
cols(6) := 'time';
DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
object_name           =>  'hrmult.locations',
method_name           =>  'MAXIMUM',
resolution_column     =>  'time',
column_list           =>  cols);
END;
/

DECLARE
cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
cols(1) := 'region_name';
cols(2) := 'time';
DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
object_name           =>  'hrmult.regions',
method_name           =>  'MAXIMUM',
resolution_column     =>  'time',
column_list           =>  cols);
END;
/

/*

手順18: mult2.example.comでの適用プロセスの起動

mult2.example.comで両方の適用プロセスを起動します。

*/

BEGIN
DBMS_APPLY_ADM.START_APPLY(
apply_name  => 'apply_from_mult1');
END;
/

BEGIN
DBMS_APPLY_ADM.START_APPLY(
apply_name  => 'apply_from_mult3');
END;
/

/*

手順19: mult3.example.comでの最新時刻に基づいた競合解消の構成

strmadminユーザーとしてmult3.example.comに接続します。

*/

CONNECT strmadmin@mult3.example.com

/*

hrmultスキーマ内の各表に更新競合ハンドラを指定します。各表で、MAXIMUM競合ハンドラの解消列としてtime列を指定します。更新の競合が発生すると、このような競合ハンドラは最新(または最大)時刻のトランザクションを適用し、それより前の(または小さい)時刻のトランザクションを廃棄します。

*/

DECLARE
cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
cols(1) := 'country_name';
cols(2) := 'region_id';
cols(3) := 'time';
DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
object_name           =>  'hrmult.countries',
method_name           =>  'MAXIMUM',
resolution_column     =>  'time',
column_list           =>  cols);
END;
/

DECLARE
cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
cols(1) := 'department_name';
cols(2) := 'manager_id';
cols(3) := 'location_id';
cols(4) := 'time';
DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
object_name           =>  'hrmult.departments',
method_name           =>  'MAXIMUM',
resolution_column     =>  'time',
column_list           =>  cols);
END;
/

DECLARE
cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
cols(1)  := 'first_name';
cols(2)  := 'last_name';
cols(3)  := 'email';
cols(4)  := 'phone_number';
cols(5)  := 'hire_date';
cols(6)  := 'job_id';
cols(7)  := 'salary';
cols(8)  := 'commission_pct';
cols(9)  := 'manager_id';
cols(10) := 'department_id';
cols(11) := 'time';
DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
object_name           =>  'hrmult.employees',
method_name           =>  'MAXIMUM',
resolution_column     =>  'time',
column_list           =>  cols);
END;
/

DECLARE
cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
cols(1) := 'job_title';
cols(2) := 'min_salary';
cols(3) := 'max_salary';
cols(4) := 'time';
DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
object_name           =>  'hrmult.jobs',
method_name           =>  'MAXIMUM',
resolution_column     =>  'time',
column_list           =>  cols);
END;
/

DECLARE
cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
cols(1) := 'employee_id';
cols(2) := 'start_date';
cols(3) := 'end_date';
cols(4) := 'job_id';
cols(5) := 'department_id';
cols(6) := 'time';
DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
object_name           =>  'hrmult.job_history',
method_name           =>  'MAXIMUM',
resolution_column     =>  'time',
column_list           =>  cols);
END;
/

DECLARE
cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
cols(1) := 'street_address';
cols(2) := 'postal_code';
cols(3) := 'city';
cols(4) := 'state_province';
cols(5) := 'country_id';
cols(6) := 'time';
DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
object_name           =>  'hrmult.locations',
method_name           =>  'MAXIMUM',
resolution_column     =>  'time',
column_list           =>  cols);
END;
/

DECLARE
cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
cols(1) := 'region_name';
cols(2) := 'time';
DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
object_name           =>  'hrmult.regions',
method_name           =>  'MAXIMUM',
resolution_column     =>  'time',
column_list           =>  cols);
END;
/

/*

手順20: mult3.example.comでの適用プロセスの起動

mult3.example.comで両方の適用プロセスを起動します。

*/

BEGIN
DBMS_APPLY_ADM.START_APPLY(
apply_name  => 'apply_from_mult1');
END;
/

BEGIN
DBMS_APPLY_ADM.START_APPLY(
apply_name  => 'apply_from_mult2');
END;
/

/*

手順21: mult1.example.comでの適用プロセスの起動

strmadminユーザーとしてmult1.example.comに接続します。

*/

CONNECT strmadmin@mult1.example.com

/*

mult1.example.comで両方の適用プロセスを起動します。

*/

BEGIN
DBMS_APPLY_ADM.START_APPLY(
apply_name  => 'apply_from_mult2');
END;
/

BEGIN
DBMS_APPLY_ADM.START_APPLY(
apply_name  => 'apply_from_mult3');
END;
/

/*

手順22: mult1.example.comでの取得プロセスの起動

mult1.example.comで取得プロセスを起動します。

*/

BEGIN
DBMS_CAPTURE_ADM.START_CAPTURE(
capture_name  => 'capture_hrmult');
END;
/

/*

手順23: mult2.example.comでの取得プロセスの起動

strmadminユーザーとしてmult2.example.comに接続します。

*/

CONNECT strmadmin@mult2.example.com

/*

mult2.example.comで取得プロセスを起動します。

*/

BEGIN
DBMS_CAPTURE_ADM.START_CAPTURE(
capture_name  => 'capture_hrmult');
END;
/

/*

手順24: mult3.example.comでの取得プロセスの起動

strmadminユーザーとしてmult3.example.comに接続します。

*/

CONNECT strmadmin@mult3.example.com

/*

mult3.example.comで取得プロセスを起動します。

*/

BEGIN
DBMS_CAPTURE_ADM.START_CAPTURE(
capture_name  => 'capture_hrmult');
END;
/

SET ECHO OFF

/*

手順25: スプール結果のチェック

streams_mult.outスプール・ファイルをチェックして、このスクリプトの完了後にすべてのアクションが正常に終了していることを確認します。

*/

SET ECHO OFF
SPOOL OFF

/*************************** END OF SCRIPT ******************************/

関連項目:
データベース・オブジェクトまたはデータベースをレプリケーション環境に追加する方法の概要は、『Oracle Streamsレプリケーション管理者ガイド』を参照してください。

hrmultスキーマ内の表に対するDML変更およびDDL変更

環境内の任意のデータベースのhrmultスキーマ内の表に対して、DML変更およびDDL変更を行うことができます。これらの変更は、環境内の他のデータベースにレプリケートされ、問合せを実行してそれらのレプリケートされたデータを表示できます。

たとえば、次の手順を実行して、mult1.example.comおよびmult2.example.comのhrmult.employees表に対してDML変更を行います。前述の手順で構成した更新競合ハンドラで更新の競合が解消されることを確認するには、これらの2つのデータベースの同じ行を変更し、ほぼ同時に変更をコミットします。環境内の各データベースで変更された行を問い合せ、変更が適切に取得、伝播および適用されたことを確認できます。

また、mult3.example.comのhrmult.jobs表に対してDDL変更を行い、変更がmult3.example.comで取得され、環境内の他のデータベースに伝播され、これらのデータベースで適用されることも確認できます。

手順1: mult.example.comおよびmult2.example.comでのhrmult.employeesに対するDML変更

次の変更を行います。競合をシミュレートするため、これらをほぼ同時にコミット(ただし、mult1.example.comでの変更をコミットした直後にmult2.example.comでの変更をコミット)します。各データベースの更新競合ハンドラによって、競合が解消されます。

CONNECT hrmult@mult1.example.com
Enter password: password

UPDATE hrmult.employees SET salary=9000 WHERE employee_id=206;
COMMIT;

CONNECT hrmult@mult2.example.com
Enter password: password

UPDATE hrmult.employees SET salary=10000 WHERE employee_id=206;
COMMIT;

手順2: mult3.example.comでのhrmult.jobs表の変更

job_title列の名前をjob_nameに変更して、hrmult.jobs表を変更します。

CONNECT hrmult@mult3.example.com
Enter password: password

ALTER TABLE hrmult.jobs RENAME COLUMN job_title TO job_name;

手順3: 各データベースでのhrmult.employees表の問合せ

手順1で実行した変更が取得、伝播および適用されてから、次の問合せを実行して、UPDATE変更が各データベースで適用されていることを確認します。

CONNECT hrmult@mult1.example.com
Enter password: password

SELECT salary FROM hrmult.employees WHERE employee_id=206;

CONNECT hrmult@mult2.example.com
Enter password: password

SELECT salary FROM hrmult.employees WHERE employee_id=206;

CONNECT hrmult@mult3.example.com
Enter password: password

SELECT salary FROM hrmult.employees WHERE employee_id=206;

すべての問合せで、salaryの値が10000と表示されるはずです。各データベースの更新競合ハンドラによって、行に対する最新の変更を適用して競合が解消されています。ここでは、行に対する最新の変更は、手順1のmult2.example.comデータベースで行われました。

手順4: 各データベースでのhrmult.jobs表の定義の表示

手順2で実行した変更が取得、伝播および適用されてから、各データベースでhrmult.jobs表の定義を表示し、ALTER TABLE変更が正常に伝播および適用されていることを確認します。

CONNECT hrmult@mult1.example.com
Enter password: password

DESC hrmult.jobs

CONNECT hrmult@mult2.example.com
Enter password: password

DESC hrmult.jobs

CONNECT hrmult@mult3.example.com
Enter password: password

DESC hrmult.jobs

各データベースでは、表の2列目にjob_nameが表示されているはずです。

4 単一データベースの取得および適用の例

この章では、単一データベースの例を説明します。例では、表に対する変更を取得し、取得した変更をキューに再エンキューします。その後、適用時にプロシージャDMLハンドラを使用して、変更のサブセットを別の表に挿入します。

ここでは、単一データベースの取得および適用の例の構成について説明します。

- 単一データベースの取得および適用の例の概要

- 前提条件

- 環境の設定

- 取得および適用の構成

- DML変更の実行、結果の問合せ、およびメッセージのデキュー

単一データベースの取得および適用の例の概要

この章の例では、Oracle Streamsを使用して、単一データベースcpap.example.comでデータ操作言語(DML)の変更を取得および適用する方法を示します。具体的には、この例ではhrスキーマ内のemployees表に対するDML変更を取得し、行の論理変更レコード(LCR)をキューstreams_queueに入れます。次に、適用プロセスによってこれらの行LCRが同じキューからデキューされ、このキューに再エンキューされてからプロシージャDMLハンドラに送信されます。

取得された行LCRは、バッファ・キューに存在することになるため、明示的にはデキューできません。適用時に行LCRを再エンキューすると、アプリケーションによる明示的なデキューに使用できるようになります。この例では、これらの行LCRをデキューするアプリケーションは作成しません。

この例では、削除された従業員のレコードをhrスキーマ内のemp_del表に挿入するプロシージャDMLハンドラについて説明します。この例では、emp_del表を使用して、削除されたすべての従業員のレコードを保持すると想定しています。プロシージャDMLハンドラを使用して、各行LCRにDELETE文が含まれているかどうかを判別します。プロシージャDMLハンドラは、DELETE文を含む行LCRを検出すると、DELETEをemp_del表に対するINSERTに変換し、その行を挿入します。

図4-1に、この環境の概要を示します。

図4-1 単一データベースの取得および適用の例

関連項目:
『Oracle Streams概要および管理』

前提条件

この章の例を開始する前に、前提条件となる次の作業を完了する必要があります。

- オプションで、STREAMS_POOL_SIZE初期化パラメータを適切な値に設定します。このパラメータでは、Oracle Streamsプールのサイズを指定します。Oracle Streamsプールは、バッファ・キューにメッセージを格納し、パラレル取得およびパラレル適用中の内部通信に使用されます。MEMORY_TARGET、MEMORY_MAX_TARGETまたはSGA_TARGET初期化パラメータを0 (ゼロ)以外の値に設定した場合、Oracle Streamsプールのサイズは自動的に管理されます。

関連項目:
Oracle Streamsに関連する初期化パラメータの設定については、『Oracle Streamsレプリケーション管理者ガイド』を参照してください。

- データベースをARCHIVELOGモードで実行するように設定します。取得される変更を生成するデータベースは、ARCHIVELOGモードで実行する必要があります。

関連項目:
ARCHIVELOGモードでデータベースを実行する方法の詳細は、『Oracle Database管理者ガイド』を参照してください。

- データベースでOracle Streams管理者を作成します。この例では、Oracle Streams管理者のユーザー名がstrmadminであると想定しています。
この例では、ストアド・プロシージャ内でOracle Streamsパッケージのサブプログラムを実行します。具体的には、手順8で作成したemp_dqプロシージャで、DBMS_STREAMS_MESSAGINGパッケージのDEQUEUEプロシージャを実行します。したがって、Oracle Streams管理者に、このパッケージに対するEXECUTE権限を明示的に付与する必要があります。この場合、EXECUTE権限はロールを介して付与することはできません。DBMS_STREAMS_AUTH.GRANT_ADMIN_PRIVILEGEプロシージャを使用すると、すべてのOracle Streamsパッケージに対するEXECUTEと、Oracle Streamsに関連するその他の権限を付与できます。パッケージに対するEXECUTE権限は、直接付与することも、GRANT_ADMIN_PRIVILEGEプロシージャを使用して付与することもできます。

関連項目:
Oracle Streams管理者を作成する方法の詳細は、『Oracle Streamsレプリケーション管理者ガイド』を参照してください。

環境の設定

次の手順を実行してhr.emp_del表を作成し、Oracle Streams管理者を設定して、キューを作成します。

1. 出力およびスプール結果の表示

2. hr.emp_del表の作成

3. Oracle Streams管理者への追加の権限の付与

4. cpap.example.comでのANYDATAキューの作成

5. スプール結果のチェック

注意:
このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。データベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。

/************************* BEGINNING OF SCRIPT ******************************

手順1: 出力およびスプール結果の表示

SET ECHO ONを実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。

*/

SET ECHO ON
SPOOL streams_setup_capapp.out

/*

手順2: hr.emp_del表の作成

hrユーザーとしてcpap.example.comに接続します。

*/

CONNECT hr@cpap.example.com

/*

hr.emp_del表を作成します。emp_del表の列は、emp_del表に行が挿入されたときにその日付を記録する追加のtimestamp列を除いて、employees表の列と同じです。

*/

CREATE TABLE emp_del(
employee_id    NUMBER(6),
first_name     VARCHAR2(20),
last_name      VARCHAR2(25),
email          VARCHAR2(25),
phone_number   VARCHAR2(20),
hire_date      DATE,
job_id         VARCHAR2(10),
salary         NUMBER(8,2),
commission_pct NUMBER(2,2),
manager_id     NUMBER(6),
department_id  NUMBER(4),
timestamp      DATE);

CREATE UNIQUE INDEX emp_del_id_pk ON emp_del (employee_id);

ALTER TABLE emp_del ADD (CONSTRAINT emp_del_id_pk PRIMARY KEY (employee_id));

/*

手順3: Oracle Streams管理者への追加の権限の付与

SYSTEMユーザーとしてcpap.example.comに接続します。

*/

CONNECT SYSTEM@cpap.example.com

/*

Oracle Streams管理者は適用ユーザーであり、emp_del表にレコードを挿入できる必要があるため、Oracle Streams管理者にこの表に対するすべての権限を付与します。または、適用プロセスを変更してhrを適用ユーザーとして指定できます。

*/

GRANT ALL ON hr.emp_del TO STRMADMIN;

/*

手順4: cpap.example.comでのANYDATAキューの作成

strmadminユーザーとしてcpap.example.comに接続します。

*/

CONNECT strmadmin@cpap.example.com

/*

SET_UP_QUEUEプロシージャを実行して、cpap.example.comでstreams_queueというキューを作成します。このキューは適用プロセスによってデキューされる取得済の変更、およびデキュー・プロシージャによってデキューされるユーザーが行った変更をステージングするANYDATAキューです。

SET_UP_QUEUEプロシージャを実行すると、次のアクションが実行されます。

- streams_queue_tableというキュー表の作成。このキュー表は、Oracle Streams管理者(strmadmin)が所有し、このユーザーのデフォルトの記憶域を使用します。

- Oracle Streams管理者(strmadmin)が所有するstreams_queueというキューの作成。

- キューの起動。

*/

BEGIN
DBMS_STREAMS_ADM.SET_UP_QUEUE(
queue_table  => 'strmadmin.streams_queue_table',
queue_name   => 'strmadmin.streams_queue');
END;
/

/*

手順5: スプール結果のチェック

streams_setup_capapp.outスプール・ファイルをチェックして、このスクリプトの完了後にすべてのアクションが正常に終了していることを確認します。

*/

SET ECHO OFF
SPOOL OFF

/*************************** END OF SCRIPT ******************************/

取得および適用の構成

次の手順を実行してhr.employees表に対する変更を取得し、プロシージャDMLハンドラを使用して、カスタマイズされた方法で単一データベースにこれらの変更を適用します。

1. 出力およびスプール結果の表示

2. cpap.example.comでの取得プロセスの構成

3. hr.employees表に対するインスタンス化SCNの設定

4. プロシージャDMLハンドラのハンドラ・プロシージャの作成

5. hr.employees表に対するプロシージャDMLハンドラの設定

6. キューのメッセージ・クライアントの作成

7. cpap.example.comでの適用プロセスの構成

8. メッセージをデキューするプロシージャの作成

9. cpap.example.comでの適用プロセスの起動

10. cpap.example.comでの取得プロセスの起動

11. スプール結果のチェック

注意:
このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。データベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。

/************************* BEGINNING OF SCRIPT ******************************

手順1: 出力およびスプール結果の表示

SET ECHO ONを実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。

*/

SET ECHO ON
SPOOL streams_config_capapp.out

/*

手順2: cpap.example.comでの取得プロセスの構成

strmadminユーザーとしてcpap.example.comに接続します。

*/

CONNECT strmadmin@cpap.example.com

/*

cpap.example.comでhr.employees表に対するDML変更を取得するように取得プロセスを構成します。この手順では、取得プロセスを作成し、そのポジティブ・ルール・セットに、この表に対するDML変更を取得するように取得プロセスに指示するルールを追加します。また、この手順では、hr.employees表をインスタンス化のために準備し、表のすべての主キー列、一意キー列、ビットマップ索引列および外部キー列のサプリメンタル・ロギングを有効にします。

サプリメンタル・ロギングによって、表に対する変更の追加の情報がREDOログに記録されます。適用プロセスでは、一意の行の識別など、一部の操作を実行するために、この追加情報が必要です。

関連項目:
『Oracle Streamsレプリケーション管理者ガイド』

*/

BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name     => 'hr.employees',
streams_type   => 'capture',
streams_name   => 'capture_emp',
queue_name     => 'strmadmin.streams_queue',
include_dml    =>  TRUE,
include_ddl    =>  FALSE,
inclusion_rule =>  TRUE);
END;
/

/*

手順3: hr.employees表に対するインスタンス化SCNの設定

この例では単一データベースで変更を取得および適用するため、インスタンス化は不要です。ただし、cpap.example.comデータベースの適用プロセスに対しては、特定のシステム変更番号(SCN)の後にhr.employees表に対して行われた変更を適用するように指示する必要があります。

この例では、DBMS_FLASHBACKパッケージのGET_SYSTEM_CHANGE_NUMBERファンクションを使用して、データベースの現行のSCNを取得します。このSCNは、DBMS_APPLY_ADMパッケージのSET_TABLE_INSTANTIATION_SCNプロシージャを実行するために使用されます。

SET_TABLE_INSTANTIATION_SCNプロシージャを使用すると、適用プロセスで無視される表のLCRと、適用プロセスで適用される表のLCRを制御できます。ソース・データベースからの表に関するLCRのコミットSCNが、接続先データベースでその表のインスタンス化SCN以下であれば、接続先データベースの適用プロセスではLCRが廃棄されます。それ以外の場合は、適用プロセスによってLCRが適用されます。この例では、cpap.example.comデータベースがソース・データベースと接続先データベースの両方になります。

適用プロセスは、この手順で取得したSCNの後にコミットされたSCNを持つトランザクションをhr.employees表に適用します。

注意:
hr.employees表にはインスタンス化のための準備も必要です。手順2の取得プロセスの構成で、hr.employees表に対するDML変更を取得するルールを追加したときに、この準備は自動的に行われています。

*/

DECLARE
iscn  NUMBER;         -- Variable to hold instantiation SCN value
BEGIN
iscn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER();
DBMS_APPLY_ADM.SET_TABLE_INSTANTIATION_SCN(
source_object_name    => 'hr.employees',
source_database_name  => 'cpap.example.com',
instantiation_scn     => iscn);
END;
/

/*

手順4: プロシージャDMLハンドラのハンドラ・プロシージャの作成

この手順を実行すると、emp_dml_handlerプロシージャが作成されます。このプロシージャは、hr.employees表に対するDELETE変更のプロシージャDMLハンドラになります。このプロシージャによって、DELETEコマンド・タイプを含むすべての行LCRがINSERTの行LCRに変換され、その行LCRを実行することで、変換された行LCRがhr.emp_del表に挿入されます。

*/

CREATE OR REPLACE PROCEDURE emp_dml_handler(in_any IN ANYDATA) IS
lcr          SYS.LCR$_ROW_RECORD;
rc           PLS_INTEGER;
command      VARCHAR2(30);
old_values   SYS.LCR$_ROW_LIST;
BEGIN
-- Access the LCR
rc := in_any.GETOBJECT(lcr);
-- Get the object command type
command := lcr.GET_COMMAND_TYPE();
-- Check for DELETE command on the hr.employees table
IF command = 'DELETE' THEN
-- Set the command_type in the row LCR to INSERT
lcr.SET_COMMAND_TYPE('INSERT');
-- Set the object_name in the row LCR to EMP_DEL
lcr.SET_OBJECT_NAME('EMP_DEL');
-- Get the old values in the row LCR
old_values := lcr.GET_VALUES('old');
-- Set the old values in the row LCR to the new values in the row LCR
lcr.SET_VALUES('new', old_values);
-- Set the old values in the row LCR to NULL
lcr.SET_VALUES('old', NULL);
-- Add a SYSDATE value for the timestamp column
lcr.ADD_COLUMN('new', 'TIMESTAMP', ANYDATA.ConvertDate(SYSDATE));
-- Apply the row LCR as an INSERT into the hr.emp_del table
lcr.EXECUTE(TRUE);
END IF;
END;
/

/*

手順5: hr.employees表に対するプロシージャDMLハンドラの設定

hr.employees表のプロシージャDMLハンドラを手順4で作成したプロシージャに設定します。表に対して実行可能な各操作(INSERT、UPDATE、DELETEなど)でプロシージャDMLハンドラが使用されるように、operation_nameパラメータをDEFAULTに設定する必要があることに注意してください。

*/

BEGIN
DBMS_APPLY_ADM.SET_DML_HANDLER(
object_name         => 'hr.employees',
object_type         => 'TABLE',
operation_name      => 'DEFAULT',
error_handler       => FALSE,
user_procedure      => 'strmadmin.emp_dml_handler',
apply_database_link => NULL,
apply_name          => NULL);
END;
/

/*

手順6: キューのメッセージ・クライアントの作成

再エンキューされたメッセージをデキューするために、アプリケーションで使用できるメッセージ・クライアントを作成します。メッセージをキューに再エンキューするには、メッセージ・クライアントを指定する必要があります。

*/

BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name     => 'hr.employees',
streams_type   => 'dequeue',
streams_name   => 'hr',
queue_name     => 'strmadmin.streams_queue',
include_dml    =>  TRUE,
include_ddl    =>  FALSE,
inclusion_rule =>  TRUE);
END;
/

/*

手順7: cpap.example.comでの適用プロセスの構成

hr.employees表に対するDML変更を適用する適用プロセスを作成します。適用プロセスのプロシージャDMLハンドラでは、削除された従業員はemp_del表に挿入されますが、キュー内の行LCRにはemp_del表ではなくemployees表に対する変更が含まれるため、このルールではemployees表を指定します。ADD_TABLE_RULESプロシージャを実行して適用プロセスを作成すると、作成したDMLルールの名前がoutパラメータdml_rule_nameに含まれます。このルール名は、SET_ENQUEUE_DESTINATIONプロシージャに渡されます。

DBMS_APPLY_ADMパッケージのSET_ENQUEUE_DESTINATIONプロシージャを実行すると、ADD_TABLE_RULESで生成されたDMLルールを使用する適用プロセスによって、このルールを満たすメッセージがstreams_queueにエンキューされるように指定されます。この場合、DMLルールは、hr.employees表に対するDML変更を含む行LCR用です。必要に応じて、適用プロセス・キュー以外のローカル・キューを指定できます。

*/

DECLARE
emp_rule_name_dml  VARCHAR2(30);
emp_rule_name_ddl  VARCHAR2(30);
BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name      => 'hr.employees',
streams_type    => 'apply',
streams_name    => 'apply_emp',
queue_name      => 'strmadmin.streams_queue',
include_dml     =>  TRUE,
include_ddl     =>  FALSE,
source_database => 'cpap.example.com',
dml_rule_name   => emp_rule_name_dml,
ddl_rule_name   => emp_rule_name_ddl);
DBMS_APPLY_ADM.SET_ENQUEUE_DESTINATION(
rule_name               =>  emp_rule_name_dml,
destination_queue_name  =>  'strmadmin.streams_queue');
END;
/

/*

手順8: メッセージをデキューするプロシージャの作成

この手順で作成するemp_dqプロシージャを使用すると、適用プロセスによって再エンキューされたメッセージをデキューできます。手順7では、SET_ENQUEUE_DESTINATIONプロシージャを使用して、hr.employees表に対する変更が含まれる行LCRをstreams_queueにエンキューするように適用プロセスに指示しました。emp_dqプロシージャを実行すると、キュー内の各行LCRがデキューされ、行LCRのコマンドのタイプ(INSERT、UPDATEまたはDELETEのいずれか)が表示されます。コマンド・タイプのみでなく、行LCR内のすべての情報にアクセスして表示できます。

関連項目:
LCR内の情報を表示する方法の詳細は、『Oracle Streams概要および管理』を参照してください。

*/

CREATE OR REPLACE PROCEDURE emp_dq (consumer IN VARCHAR2) AS
msg            ANYDATA;
row_lcr        SYS.LCR$_ROW_RECORD;
num_var        pls_integer;
more_messages  BOOLEAN := TRUE;
navigation     VARCHAR2(30);
BEGIN
navigation := 'FIRST MESSAGE';
WHILE (more_messages) LOOP
BEGIN
DBMS_STREAMS_MESSAGING.DEQUEUE(
queue_name   => 'strmadmin.streams_queue',
streams_name => consumer,
payload      => msg,
navigation   => navigation,
wait         => DBMS_STREAMS_MESSAGING.NO_WAIT);
IF msg.GETTYPENAME() = 'SYS.LCR$_ROW_RECORD' THEN
num_var := msg.GetObject(row_lcr);
DBMS_OUTPUT.PUT_LINE(row_lcr.GET_COMMAND_TYPE || ' row LCR dequeued');
END IF;
navigation := 'NEXT MESSAGE';
COMMIT;
EXCEPTION WHEN SYS.DBMS_STREAMS_MESSAGING.ENDOFCURTRANS THEN
navigation := 'NEXT TRANSACTION';
WHEN DBMS_STREAMS_MESSAGING.NOMOREMSGS THEN
more_messages := FALSE;
DBMS_OUTPUT.PUT_LINE('No more messages.');
WHEN OTHERS THEN
RAISE;
END;
END LOOP;
END;
/

/*

手順9: cpap.example.comでの適用プロセスの起動

エラーが発生した場合に適用プロセスが無効化されないように、disable_on_errorパラメータをnに設定して、cpap.example.comで適用プロセスを起動します。

*/

BEGIN
DBMS_APPLY_ADM.SET_PARAMETER(
apply_name  => 'apply_emp',
parameter   => 'disable_on_error',
value       => 'N');
END;
/

BEGIN
DBMS_APPLY_ADM.START_APPLY(
apply_name  => 'apply_emp');
END;
/

/*

手順10: cpap.example.comでの取得プロセスの起動

cpap.example.comで取得プロセスを起動します。

*/

BEGIN
DBMS_CAPTURE_ADM.START_CAPTURE(
capture_name  => 'capture_emp');
END;
/

/*

手順11: スプール結果のチェック

streams_config_capapp.outスプール・ファイルをチェックして、このスクリプトの完了後にすべてのアクションが正常に終了していることを確認します。

*/

SET ECHO OFF
SPOOL OFF

/*************************** END OF SCRIPT ******************************/

DML変更の実行、結果の問合せ、およびメッセージのデキュー

次の手順を実行して適用プロセスが正しく構成されていることを確認し、hr.employees表に対するDML変更を実行して、その結果であるhr.emp_del表への挿入と、streams_queue_tableに再エンキューされたメッセージを問い合せ、適用プロセスによって再エンキューされたメッセージをデキューします。

1. ルールのアクション・コンテキストの確認

2. hr.employeesに対するINSERT、UPDATEおよびDELETEの実行

3. hr.emp_del表およびstreams_queue_tableの問合せ

4. プロシージャDMLハンドラによって再エンキューされたメッセージのデキュー

手順1: ルールのアクション・コンテキストの確認

手順7では、ルールを満たすLCRのエンキュー先となる宛先キューを指定する適用プロセス・ルールを作成しています。この場合、ルールを満たすLCRとは、hr.employees表に対する変更を含む行LCRです。

次の手順を実行して、ルールが宛先キューを指定していることを確認します。

1. 次の問合せを実行し、適用プロセスapply_empで使用されるhr.employees表に対するDML変更のルール名を判断します。

CONNECT strmadmin@cpap.example.com
Enter password: password

SELECT RULE_OWNER, RULE_NAME FROM DBA_STREAMS_RULES
WHERE STREAMS_NAME = 'APPLY_EMP' AND
STREAMS_TYPE = 'APPLY' AND
SCHEMA_NAME  = 'HR' AND
OBJECT_NAME  = 'EMPLOYEES' AND
RULE_TYPE    = 'DML'
ORDER BY RULE_NAME;

出力は次のようになります。

RULE_OWNER                     RULE_NAME
------------------------------ ------------------------------
STRMADMIN                      EMPLOYEES3

2. 手順1の問合せで戻されたルールのアクション・コンテキストを表示します。

COLUMN RULE_OWNER HEADING 'Rule Owner' FORMAT A15
COLUMN DESTINATION_QUEUE_NAME HEADING 'Destination Queue' FORMAT A30

SELECT RULE_OWNER, DESTINATION_QUEUE_NAME
FROM DBA_APPLY_ENQUEUE
WHERE RULE_NAME = 'EMPLOYEES3'
ORDER BY DESTINATION_QUEUE_NAME;

手順1で戻されたルール名をWHERE句に代入します。出力は次のようになります。

Rule Owner      Destination Queue
--------------- ------------------------------
STRMADMIN       "STRMADMIN"."STREAMS_QUEUE"

出力には、適用プロセス・ルールを満たすLCRがstreams_queueにエンキューされることが示されます。

手順2: hr.employeesに対するINSERT、UPDATEおよびDELETEの実行

hr.employees表に次のDML変更を行います。

CONNECT hr@cpap.example.com
Enter password: password

INSERT INTO hr.employees VALUES(207, 'JOHN', 'SMITH', 'JSMITH@EXAMPLE.COM',
NULL, '07-JUN-94', 'AC_ACCOUNT', 777, NULL, NULL, 110);
COMMIT;

UPDATE hr.employees SET salary=5999 WHERE employee_id=207;
COMMIT;

DELETE FROM hr.employees WHERE employee_id=207;
COMMIT;

手順3: hr.emp_del表およびstreams_queue_tableの問合せ

前述の手順で行った変更が取得および適用されてから、次の問合せを実行して結果を確認します。

CONNECT strmadmin@cpap.example.com
Enter password: password

SELECT employee_id, first_name, last_name, timestamp
FROM hr.emp_del ORDER BY employee_id;

SELECT MSG_ID, MSG_STATE, CONSUMER_NAME
FROM AQ$STREAMS_QUEUE_TABLE ORDER BY MSG_ID;

最初の問合せを実行すると、employee_idが207の従業員のレコードが表示されます。この従業員は前述の手順で削除されています。2番目の問合せを実行すると、前述の手順で行ったすべての変更の結果として再エンキューされたメッセージが表示され、これらのメッセージのMSG_STATEがREADYであることを確認できます。

手順4: プロシージャDMLハンドラによって再エンキューされたメッセージのデキュー

emp_dqプロシージャを使用して、プロシージャDMLハンドラによって再エンキューされたメッセージをデキューします。

SET SERVEROUTPUT ON SIZE 100000

EXEC emp_dq('HR');

DML文で変更された各行に対して1行が戻され、各行には変更のコマンド・タイプ(INSERT、UPDATEまたはDELETE)が示されます。メッセージのデキュー後に手順3のキュー表に問合せを繰り返すと、デキューされたメッセージはコンシュームされているはずです。つまり、これらのメッセージのMSG_STATEがPROCESSEDであるか、またはメッセージがキューに存在しません。

SELECT MSG_ID, MSG_STATE, CONSUMER_NAME
FROM AQ$STREAMS_QUEUE_TABLE ORDER BY MSG_ID;

5 LOBを含む論理変更レコードの例

この章では、LOBを含むLCRを構成およびエンキューするPL/SQLプロシージャを作成する例を説明します。

この章の内容は次のとおりです。

- LOBを含むLCRを構成およびエンキューするスクリプトの例

LOBを含むLCRを構成およびエンキューするスクリプトの例

1. 出力およびスプール結果の表示

2. Oracle Streams管理者へのDBMS_STREAMS_MESSAGINGに対するEXECUTE権限の付与

3. Oracle Streams管理者としての接続

4. ANYDATAキューの作成

5. 適用プロセスの作成および起動

6. LOB列を含む表が存在するスキーマの作成

7. Oracle Streams管理者への表に対する必要な権限の付与

8. LOBを含むLCRをエンキューするPL/SQLプロシージャの作成

9. CLOBデータをエンキューするdo_enq_clobファンクションの作成

10. do_enq_clobファンクションを使用したCLOBデータのエンキュー

11. スプール結果のチェック

注意:
このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。

/************************* BEGINNING OF SCRIPT ******************************

手順1: 出力およびスプール結果の表示

SET ECHO ONを実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。

*/

SET ECHO ON
SPOOL lob_construct.out

/*

手順2: Oracle Streams管理者へのDBMS_STREAMS_MESSAGINGに対するEXECUTE権限の付与

手順8のPL/SQLプロシージャ内でこのパッケージのプロシージャをコールするため、このパッケージに対する明示的なEXECUTE権限が必要です。

*/

CONNECT / AS SYSDBA;

GRANT EXECUTE ON DBMS_STREAMS_MESSAGING TO strmadmin;

/*

手順3: Oracle Streams管理者としての接続

*/

SET ECHO ON
SET FEEDBACK 1
SET NUMWIDTH 10
SET LINESIZE 80
SET TRIMSPOOL ON
SET TAB OFF
SET PAGESIZE 100
SET SERVEROUTPUT ON SIZE 100000

CONNECT strmadmin

/*

手順4: ANYDATAキューの作成

*/

BEGIN
DBMS_STREAMS_ADM.SET_UP_QUEUE(
queue_table => 'lobex_queue_table',
queue_name  => 'lobex_queue');
END;
/

/*

手順5: 適用プロセスの作成および起動

*/

BEGIN
DBMS_APPLY_ADM.CREATE_APPLY(
queue_name      => 'strmadmin.lobex_queue',
apply_name      => 'apply_lob',
apply_captured  => FALSE);
END;
/

BEGIN
DBMS_APPLY_ADM.SET_PARAMETER(
apply_name => 'apply_lob',
parameter  => 'disable_on_error',
value      => 'N');
END;
/

BEGIN
DBMS_APPLY_ADM.START_APPLY(
'apply_lob');
END;
/

/*

手順6: LOB列を含む表が存在するスキーマの作成

*/

CONNECT system

CREATE TABLESPACE lob_user_tbs DATAFILE 'lob_user_tbs.dbf'
SIZE 5M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;

ACCEPT password PROMPT 'Enter password for user: ' HIDE

CREATE USER lob_user
IDENTIFIED BY &password
DEFAULT TABLESPACE lob_user_tbs
QUOTA UNLIMITED ON lob_user_tbs;

GRANT ALTER SESSION, CREATE CLUSTER, CREATE DATABASE LINK, CREATE SEQUENCE,
CREATE SESSION, CREATE SYNONYM, CREATE TABLE, CREATE VIEW, CREATE INDEXTYPE,
CREATE OPERATOR, CREATE PROCEDURE, CREATE TRIGGER, CREATE TYPE
TO lob_user;

CONNECT lob_user/lob_user_pw

CREATE TABLE with_clob (a  NUMBER PRIMARY KEY,
c1 CLOB,
c2 CLOB,
c3 CLOB);

CREATE TABLE with_blob (a NUMBER PRIMARY KEY,
b BLOB);

/*

手順7: Oracle Streams管理者への表に対する必要な権限の付与

次の権限を付与すると、Oracle Streams管理者は、LOBオフセット長を取得し、表にDML操作を実行できるようになります。

*/

GRANT ALL ON with_clob TO strmadmin;
GRANT ALL ON with_blob TO strmadmin;
COMMIT;

/*

手順8: LOBを含むLCRをエンキューするPL/SQLプロシージャの作成

*/

CONNECT strmadmin

CREATE OR REPLACE PROCEDURE enq_row_lcr(source_dbname  VARCHAR2,
cmd_type       VARCHAR2,
obj_owner      VARCHAR2,
obj_name       VARCHAR2,
old_vals       SYS.LCR$_ROW_LIST,
new_vals       SYS.LCR$_ROW_LIST) AS
xr_lcr         SYS.LCR$_ROW_RECORD;
BEGIN
xr_lcr := SYS.LCR$_ROW_RECORD.CONSTRUCT(
source_database_name => source_dbname,
command_type         => cmd_type,
object_owner         => obj_owner,
object_name          => obj_name,
old_values           => old_vals,
new_values           => new_vals);
-- Enqueue a row lcr
DBMS_STREAMS_MESSAGING.ENQUEUE(
queue_name         => 'lobex_queue',
payload            => ANYDATA.ConvertObject(xr_lcr));
END enq_row_lcr;
/
SHOW ERRORS

/*

手順9: CLOBデータをエンキューするdo_enq_clobファンクションの作成

*/

-- Description of each variable:
-- src_dbname  : Source database name
-- tab_owner   : Table owner
-- tab_name    : Table name
-- col_name    : Name of the CLOB column
-- new_vals    : SYS.LCR$_ROW_LIST containing primary key and supplementally
--               logged colums
-- clob_data   : CLOB that contains data to be sent
-- offset      : Offset from which data should be sent, default is 1
-- lsize       : Size of data to be sent, default is 0
-- chunk_size  : Size used for creating LOB chunks, default is 2048

CREATE OR REPLACE FUNCTION do_enq_clob(src_dbname     VARCHAR2,
tab_owner      VARCHAR2,
tab_name       VARCHAR2,
col_name       VARCHAR2,
new_vals       SYS.LCR$_ROW_LIST,
clob_data      CLOB,
offset         NUMBER default 1,
lsize          NUMBER default 0,
chunk_size     NUMBER default 2048)
RETURN NUMBER IS
lob_offset NUMBER; -- maintain lob offset
newunit    SYS.LCR$_ROW_UNIT;
tnewvals   SYS.LCR$_ROW_LIST;
lob_flag   NUMBER;
lob_data   VARCHAR2(32767);
lob_size   NUMBER;
unit_pos   NUMBER;
final_size NUMBER;
exit_flg   BOOLEAN;
c_size     NUMBER;
i          NUMBER;
BEGIN
lob_size := DBMS_LOB.GETLENGTH(clob_data);
unit_pos := new_vals.count + 1;
tnewvals := new_vals;
c_size   := chunk_size;
i := 0;
-- validate parameters
IF (unit_pos <= 1) THEN
DBMS_OUTPUT.PUT_LINE('Invalid new_vals list');
RETURN 1;
END IF;

IF (c_size < 1) THEN
DBMS_OUTPUT.PUT_LINE('Invalid LOB chunk size');
RETURN 1;
END IF;

IF (lsize < 0 OR lsize > lob_size) THEN
DBMS_OUTPUT.PUT_LINE('Invalid LOB size');
RETURN 1;
END IF;

IF (offset < 1 OR offset >= lob_size) THEN
DBMS_OUTPUT.PUT_LINE('Invalid lob offset');
RETURN 1;
ELSE
lob_offset := offset;
END IF;

-- calculate final size
IF (lsize = 0) THEN
final_size := lob_size;
ELSE
final_size := lob_offset + lsize;
END IF;

--  The following output lines are for debugging purposes only.
-- DBMS_OUTPUT.PUT_LINE('Final size: ' || final_size);
-- DBMS_OUTPUT.PUT_LINE('Lob size: ' || lob_size);

IF (final_size < 1 OR final_size > lob_size) THEN
DBMS_OUTPUT.PUT_LINE('Invalid lob size');
RETURN 1;
END IF;

-- expand new_vals list for LOB column
tnewvals.extend();

exit_flg := FALSE;

-- Enqueue all LOB chunks
LOOP
--  The following output line is for debugging purposes only.
DBMS_OUTPUT.PUT_LINE('About to write chunk#' || i);
i := i + 1;

-- check if last LOB chunk
IF ((lob_offset + c_size) < final_size) THEN
lob_flag := DBMS_LCR.LOB_CHUNK;
ELSE
lob_flag := DBMS_LCR.LAST_LOB_CHUNK;
exit_flg := TRUE;
--  The following output line is for debugging purposes only.
DBMS_OUTPUT.PUT_LINE('Last LOB chunk');
END IF;

--  The following output lines are for debugging purposes only.
DBMS_OUTPUT.PUT_LINE('lob offset: ' || lob_offset);
DBMS_OUTPUT.PUT_LINE('Chunk size: ' || to_char(c_size));

lob_data := DBMS_LOB.SUBSTR(clob_data, c_size, lob_offset);

-- create row unit for clob
newunit := SYS.LCR$_ROW_UNIT(col_name,
ANYDATA.ConvertVarChar2(lob_data),
lob_flag,
lob_offset,
NULL);

-- insert new LCR$_ROW_UNIT
tnewvals(unit_pos) := newunit;

-- enqueue lcr
enq_row_lcr(
source_dbname => src_dbname,
cmd_type      => 'LOB WRITE',
obj_owner     => tab_owner,
obj_name      => tab_name,
old_vals      => NULL,
new_vals      => tnewvals);

-- calculate next chunk size
lob_offset := lob_offset + c_size;

IF ((final_size - lob_offset) < c_size) THEN
c_size := final_size - lob_offset + 1;
END IF;

--  The following output line is for debugging purposes only.
DBMS_OUTPUT.PUT_LINE('Next chunk size : ' || TO_CHAR(c_size));

IF (c_size < 1) THEN
exit_flg := TRUE;
END IF;

EXIT WHEN exit_flg;

END LOOP;

RETURN 0;
END do_enq_clob;
/

SHOW ERRORS

/*

手順10: do_enq_clobファンクションを使用したCLOBデータのエンキュー

次の例に示すDBMS_OUTPUT行は、必要に応じて、デバッグのために使用できます。この行が不要な場合は、コメント・アウトまたは削除できます。

*/

SET SERVEROUTPUT ON SIZE 100000
DECLARE
c1_data CLOB;
c2_data CLOB;
c3_data CLOB;
newunit1 SYS.LCR$_ROW_UNIT;
newunit2 SYS.LCR$_ROW_UNIT;
newunit3 SYS.LCR$_ROW_UNIT;
newunit4 SYS.LCR$_ROW_UNIT;
newvals  SYS.LCR$_ROW_LIST;
big_data VARCHAR(22000);
n        NUMBER;
BEGIN
-- Create primary key for LCR$_ROW_UNIT
newunit1 := SYS.LCR$_ROW_UNIT('A',
ANYDATA.ConvertNumber(3),
NULL,
NULL,
NULL);
-- Create empty CLOBs
newunit2 := sys.lcr$_row_unit('C1',
ANYDATA.ConvertVarChar2(NULL),
DBMS_LCR.EMPTY_LOB,
NULL,
NULL);
newunit3 := SYS.LCR$_ROW_UNIT('C2',
ANYDATA.ConvertVarChar2(NULL),
DBMS_LCR.EMPTY_LOB,
NULL,
NULL);
newunit4 := SYS.LCR$_ROW_UNIT('C3',
ANYDATA.ConvertVarChar2(NULL),
DBMS_LCR.EMPTY_LOB,
NULL,
NULL);
newvals := SYS.LCR$_ROW_LIST(newunit1,newunit2,newunit3,newunit4);

-- Perform an insert
enq_row_lcr(
source_dbname => 'MYDB.EXAMPLE.COM',
cmd_type      => 'INSERT',
obj_owner     => 'LOB_USER',
obj_name      => 'WITH_CLOB',
old_vals      => NULL,
new_vals      => newvals);

-- construct clobs
big_data := RPAD('Hello World', 1000, '_');
big_data := big_data || '#';
big_data := big_data || big_data || big_data || big_data || big_data;
DBMS_LOB.CREATETEMPORARY(
lob_loc => c1_data,
cache   => TRUE);
DBMS_LOB.WRITEAPPEND(
lob_loc => c1_data,
amount  => length(big_data),
buffer  => big_data);

big_data := RPAD('1234567890#', 1000, '_');
big_data := big_data || big_data || big_data || big_data;
DBMS_LOB.CREATETEMPORARY(
lob_loc => c2_data,
cache   => TRUE);
DBMS_LOB.WRITEAPPEND(
lob_loc => c2_data,
amount  => length(big_data),
buffer  => big_data);

big_data := RPAD('ASDFGHJKLQW', 2000, '_');
big_data := big_data || '#';
big_data := big_data || big_data || big_data || big_data || big_data;
DBMS_LOB.CREATETEMPORARY(
lob_loc => c3_data,
cache   => TRUE);
DBMS_LOB.WRITEAPPEND(
lob_loc => c3_data,
amount  => length(big_data),
buffer  => big_data);

-- pk info
newunit1 := SYS.LCR$_ROW_UNIT('A',
ANYDATA.ConvertNumber(3),
NULL,
NULL,
NULL);
newvals  := SYS.LCR$_ROW_LIST(newunit1);

-- write c1 clob
n := do_enq_clob(
src_dbname => 'MYDB.EXAMPLE.COM',
tab_owner  => 'LOB_USER',
tab_name   => 'WITH_CLOB',
col_name   => 'C1',
new_vals   => newvals,
clob_data  => c1_data,
offset     => 1,
chunk_size => 1024);
DBMS_OUTPUT.PUT_LINE('n=' || n);

-- write c2 clob
newvals  := SYS.LCR$_ROW_LIST(newunit1);
n := do_enq_clob(
src_dbname => 'MYDB.EXAMPLE.COM',
tab_owner  => 'LOB_USER',
tab_name   => 'WITH_CLOB',
col_name   => 'C2',
new_vals   => newvals,
clob_data  => c2_data,
offset     => 1,
chunk_size => 2000);
DBMS_OUTPUT.PUT_LINE('n=' || n);

-- write c3 clob
newvals  := SYS.LCR$_ROW_LIST(newunit1);
n := do_enq_clob(src_dbname=>'MYDB.EXAMPLE.COM',
tab_owner  => 'LOB_USER',
tab_name   => 'WITH_CLOB',
col_name   => 'C3',
new_vals   => newvals,
clob_data  => c3_data,
offset     => 1,
chunk_size => 500);
DBMS_OUTPUT.PUT_LINE('n=' || n);

COMMIT;

END;
/

/*

手順11: スプール結果のチェック

lob_construct.outスプール・ファイルをチェックして、このスクリプトの完了後にすべてのアクションが正常に終了していることを確認します。

*/

SET ECHO OFF
SPOOL OFF

/*************************** END OF SCRIPT ******************************/

スクリプトの実行後に、lob_user.with_clob表を問い合せて、適用プロセスによって適用された行を表示できます。DBMS_LOCK.SLEEP文を使用して、エンキューされた行を適用プロセスが適用するための時間のロックを指定します。

CONNECT lob_user/lob_user_pw

EXECUTE DBMS_LOCK.SLEEP(10);

SELECT a, c1, c2, c3 FROM with_clob ORDER BY a;

SELECT a, LENGTH(c1), LENGTH(c2), LENGTH(c3) FROM with_clob ORDER BY a;

6 ルールベースのアプリケーションの例

この章では、Oracleルール・エンジンを使用するルールベースのアプリケーションについて説明します。

この章の例は、Oracle Streamsとは関係ありません。つまり、これらの例では、Oracle Streamsの取得プロセス、伝播、適用プロセスまたはメッセージ・クライアントはルール・エンジンのクライアントではなく、キューも使用されません。

ここでは、ルールベースのアプリケーションの例の構成について説明します。

- ルールベースのアプリケーションの概要

- 明示的変数に格納された表以外のデータに対するルールの使用

- 繰返しの結果を持つ明示的変数内のデータに対するルールの使用

- 明示的変数内のデータに対するルールの部分評価の使用

- 表に格納されたデータに対するルールの使用

- 明示的変数と表データの両方に対するルールの使用

- 暗黙的変数および表データに対するルールの使用

- イベント・コンテキストおよび暗黙的変数のルールとの併用

- 問題のディスパッチおよび表の例の結果のチェック

関連項目:
『Oracle Streams概要および管理』

ルールベースのアプリケーションの概要

この章の各例では、顧客の問題を処理するルールベースのアプリケーションを作成します。アプリケーションでは、新しい問題がレポートされると、ルールを使用し、問題の優先度に基づいて必要なアクションを決定します。たとえば、アプリケーションでは、それぞれの問題をその優先度に基づいて社内の特定のセンターに割り当てます。

アプリケーションは、これらのルールがルール・エンジンを使用して規定されます。サポートの問題に関連する情報を定義するために、評価コンテキストevalctxが作成されます。ルールは前述の要件に基づいて作成され、ルール・セットrsに追加されます。

問題を割り当てるタスクは、ユーザー定義プロシージャproblem_dispatchによって実行されます。このプロシージャは、ルール・エンジンをコールしてルール・セットrs内のルールを評価し、TRUEと評価されるルールに基づいて適切なアクションを実行します。

明示的変数に格納された表以外のデータに対するルールの使用

この例では、ルールを使用して、明示的変数に格納されたデータを評価する方法について説明します。この例では、優先度に基づいて顧客の問題を処理し、次のルールを使用して顧客の問題を処理します。

- 優先度が2より大きいすべての問題は、サンノゼ・センターに割り当てます。

- 優先度が2以下のすべての問題は、ニューヨーク・センターに割り当てます。

- 優先度が1の問題については、サポート責任者にアラートが送信されます。

評価コンテキストには、ディスパッチしている問題の優先度を示す、priorityという1つの明示的変数のみが含まれています。この変数の値は、problem_dispatchプロシージャによって、DBMS_RULE.EVALUATEプロシージャに渡されます。

次の手順を実行します。

1. 出力およびスプール結果の表示

2. supportユーザーの作成

3. supportユーザーへのルールに対する必要なシステム権限の付与

4. 評価コンテキストevalctxの作成

5. 問題の優先度に対応するルールの作成

6. ルール・セットrsの作成

7. ルール・セットへのルールの追加

8. データ・ディクショナリの問合せ

9. PL/SQLプロシージャproblem_dispatchの作成

10. サンプル問題のディスパッチ

11. スプール結果のチェック

注意:
このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。

/************************* BEGINNING OF SCRIPT ******************************

手順1: 出力およびスプール結果の表示

SET ECHO ONを実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。

*/

SET ECHO ON
SPOOL rules_stored_variables.out

/*

手順2: supportユーザーの作成

*/

CONNECT SYSTEM

ACCEPT password PROMPT 'Enter password for user: ' HIDE

GRANT ALTER SESSION, CREATE CLUSTER, CREATE DATABASE LINK, CREATE SEQUENCE,
CREATE SESSION, CREATE SYNONYM, CREATE TABLE, CREATE VIEW, CREATE INDEXTYPE,
CREATE OPERATOR, CREATE PROCEDURE, CREATE TRIGGER, CREATE TYPE
TO support IDENTIFIED BY &password;

/*

手順3: supportユーザーへのルールに対する必要なシステム権限の付与

*/

BEGIN
DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE(
privilege    => DBMS_RULE_ADM.CREATE_RULE_SET_OBJ,
grantee      => 'support',
grant_option => FALSE);
DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE(
privilege    => DBMS_RULE_ADM.CREATE_RULE_OBJ,
grantee      => 'support',
grant_option => FALSE);
DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE(
privilege    => DBMS_RULE_ADM.CREATE_EVALUATION_CONTEXT_OBJ,
grantee      => 'support',
grant_option => FALSE);
END;
/

/*

手順4: 評価コンテキストevalctxの作成

*/

CONNECT support

SET FEEDBACK 1
SET NUMWIDTH 10
SET LINESIZE 80
SET TRIMSPOOL ON
SET TAB OFF
SET PAGESIZE 100
SET SERVEROUTPUT ON
DECLARE
vt SYS.RE$VARIABLE_TYPE_LIST;
BEGIN
vt := SYS.RE$VARIABLE_TYPE_LIST(
SYS.RE$VARIABLE_TYPE('priority', 'NUMBER', NULL, NULL));
DBMS_RULE_ADM.CREATE_EVALUATION_CONTEXT(
evaluation_context_name    => 'evalctx',
variable_types             => vt,
evaluation_context_comment => 'support problem definition');
END;
/

/*

手順5: 問題の優先度に対応するルールの作成

次のコードを実行すると、それぞれが1つの名前/値ペアを持つアクション・コンテキストが、各ルールに1つずつ作成されます。

*/

DECLARE
ac  SYS.RE$NV_LIST;
BEGIN
ac := SYS.RE$NV_LIST(NULL);
ac.ADD_PAIR('CENTER', ANYDATA.CONVERTVARCHAR2('San Jose'));
DBMS_RULE_ADM.CREATE_RULE(
rule_name      => 'r1',
condition      => ':priority > 2',
action_context => ac,
rule_comment   => 'Low priority problems');
ac := SYS.RE$NV_LIST(NULL);
ac.ADD_PAIR('CENTER', ANYDATA.CONVERTVARCHAR2('New York'));
DBMS_RULE_ADM.CREATE_RULE(
rule_name      => 'r2',
condition      => ':priority <= 2',
action_context => ac,
rule_comment   => 'High priority problems');
ac := SYS.RE$NV_LIST(NULL);
ac.ADD_PAIR('ALERT', ANYDATA.CONVERTVARCHAR2('John Doe'));
DBMS_RULE_ADM.CREATE_RULE(
rule_name      => 'r3',
condition      => ':priority = 1',
action_context => ac,
rule_comment   => 'Urgent problems');
END;
/

/*

手順6: ルール・セットrsの作成

*/

BEGIN
DBMS_RULE_ADM.CREATE_RULE_SET(
rule_set_name      => 'rs',
evaluation_context => 'evalctx',
rule_set_comment   => 'support rules');
END;
/

/*

手順7: ルール・セットへのルールの追加

*/

BEGIN
DBMS_RULE_ADM.ADD_RULE(
rule_name     => 'r1',
rule_set_name => 'rs');
DBMS_RULE_ADM.ADD_RULE(
rule_name     => 'r2',
rule_set_name => 'rs');
DBMS_RULE_ADM.ADD_RULE(
rule_name     => 'r3',
rule_set_name => 'rs');
END;
/

/*

手順8: データ・ディクショナリの問合せ

この時点で、前述の手順で作成した評価コンテキスト、ルールおよびルール・セットを表示できます。

*/

COLUMN EVALUATION_CONTEXT_NAME HEADING 'Eval Context Name' FORMAT A30
COLUMN EVALUATION_CONTEXT_COMMENT HEADING 'Eval Context Comment' FORMAT A40

SELECT EVALUATION_CONTEXT_NAME, EVALUATION_CONTEXT_COMMENT
FROM USER_EVALUATION_CONTEXTS
ORDER BY EVALUATION_CONTEXT_NAME;

SET LONGCHUNKSIZE 4000
SET LONG 4000
COLUMN RULE_NAME HEADING 'Rule|Name' FORMAT A5
COLUMN RULE_CONDITION HEADING 'Rule Condition' FORMAT A35
COLUMN ACTION_CONTEXT_NAME HEADING 'Action|Context|Name' FORMAT A10
COLUMN ACTION_CONTEXT_VALUE HEADING 'Action|Context|Value' FORMAT A10

SELECT RULE_NAME,
RULE_CONDITION,
AC.NVN_NAME ACTION_CONTEXT_NAME,
AC.NVN_VALUE.ACCESSVARCHAR2() ACTION_CONTEXT_VALUE
FROM USER_RULES R, TABLE(R.RULE_ACTION_CONTEXT.ACTX_LIST) AC
ORDER BY RULE_NAME;

COLUMN RULE_SET_NAME HEADING 'Rule Set Name' FORMAT A20
COLUMN RULE_SET_EVAL_CONTEXT_OWNER HEADING 'Eval Context|Owner' FORMAT A12
COLUMN RULE_SET_EVAL_CONTEXT_NAME HEADING 'Eval Context Name' FORMAT A25
COLUMN RULE_SET_COMMENT HEADING 'Rule Set|Comment' FORMAT A15

SELECT RULE_SET_NAME,
RULE_SET_EVAL_CONTEXT_OWNER,
RULE_SET_EVAL_CONTEXT_NAME,
RULE_SET_COMMENT
FROM USER_RULE_SETS
ORDER BY RULE_SET_NAME;

/*

手順9: PL/SQLプロシージャproblem_dispatchの作成

*/

CREATE OR REPLACE PROCEDURE problem_dispatch (priority NUMBER)
IS
vv        SYS.RE$VARIABLE_VALUE;
vvl       SYS.RE$VARIABLE_VALUE_LIST;
truehits  SYS.RE$RULE_HIT_LIST;
maybehits SYS.RE$RULE_HIT_LIST;
ac        SYS.RE$NV_LIST;
namearray SYS.RE$NAME_ARRAY;
name      VARCHAR2(30);
cval      VARCHAR2(100);
rnum      INTEGER;
i         INTEGER;
status    PLS_INTEGER;
BEGIN
vv  := SYS.RE$VARIABLE_VALUE('priority',
ANYDATA.CONVERTNUMBER(priority));
vvl := SYS.RE$VARIABLE_VALUE_LIST(vv);
truehits := SYS.RE$RULE_HIT_LIST();
maybehits := SYS.RE$RULE_HIT_LIST();
DBMS_RULE.EVALUATE(
rule_set_name        => 'support.rs',
evaluation_context   => 'evalctx',
variable_values      => vvl,
true_rules           => truehits,
maybe_rules          => maybehits);
FOR rnum IN 1..truehits.COUNT LOOP
DBMS_OUTPUT.PUT_LINE('Using rule '|| truehits(rnum).rule_name);
ac := truehits(rnum).rule_action_context;
namearray := ac.GET_ALL_NAMES;
FOR i IN 1..namearray.count loop
name := namearray(i);
status := ac.GET_VALUE(name).GETVARCHAR2(cval);
IF (name = 'CENTER') then
DBMS_OUTPUT.PUT_LINE('Assigning problem to ' || cval);
ELSIF (name = 'ALERT') THEN
DBMS_OUTPUT.PUT_LINE('Sending alert to: '|| cval);
END IF;
END LOOP;
END LOOP;
END;
/

/*

手順10: サンプル問題のディスパッチ

*/

EXECUTE problem_dispatch(1);
EXECUTE problem_dispatch(2);
EXECUTE problem_dispatch(3);
EXECUTE problem_dispatch(5);

/*

手順11: スプール結果のチェック

rules_stored_variables.outスプール・ファイルをチェックして、このスクリプトの完了後にすべてのアクションが正常に終了していることを確認します。

*/

SET ECHO OFF
SPOOL OFF

/*************************** END OF SCRIPT ******************************/

繰返しの結果を持つ明示的変数内のデータに対するルールの使用

この例は、すべての評価結果が一度に戻されるのではなく繰返し戻されることを除き、「明示的変数に格納された表以外のデータに対するルールの使用」の例と同じです。

次の手順を実行します。

1. 出力およびスプール結果の表示

2. 前述の手順が完了したことの確認

3. PL/SQLプロシージャproblem_dispatchの置換え

4. サンプル問題のディスパッチ

5. 環境のクリーンアップ(オプション)

6. スプール結果のチェック

注意:
このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。

/************************* BEGINNING OF SCRIPT ******************************

手順1: 出力およびスプール結果の表示

SET ECHO ONを実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。

*/

SET ECHO ON
SPOOL rules_stored_variables_iterative.out

/*

手順2: 前述の手順が完了したことの確認

「明示的変数に格納された表以外のデータに対するルールの使用」の手順1から8を完了していることを確認します。これらの手順を完了していない場合は、完了してから次の手順に進みます。

*/

PAUSE Press <RETURN> to continue when the preliminary steps have been completed.

/*

手順3: PL/SQLプロシージャproblem_dispatchの置換え

手順9で作成したproblem_dispatchプロシージャをこの手順のプロシージャに置き換えます。2つのプロシージャの相違点は、手順9で作成したプロシージャはすべての評価結果を一度に戻すのに対し、この手順のプロシージャは評価結果を繰返し戻すことです。

*/

CONNECT support

SET SERVEROUTPUT ON
CREATE OR REPLACE PROCEDURE problem_dispatch (priority NUMBER)
IS
vv          SYS.RE$VARIABLE_VALUE;
vvl         SYS.RE$VARIABLE_VALUE_LIST;
truehits    BINARY_INTEGER;
maybehits   BINARY_INTEGER;
hit         SYS.RE$RULE_HIT;
ac          SYS.RE$NV_LIST;
namearray   SYS.RE$NAME_ARRAY;
name        VARCHAR2(30);
cval        VARCHAR2(100);
i           INTEGER;
status      PLS_INTEGER;
iter_closed EXCEPTION;
pragma exception_init(iter_closed, -25453);
BEGIN
vv  := SYS.RE$VARIABLE_VALUE('priority',
ANYDATA.CONVERTNUMBER(priority));
vvl := SYS.RE$VARIABLE_VALUE_LIST(vv);
DBMS_RULE.EVALUATE(
rule_set_name        => 'support.rs',
evaluation_context   => 'evalctx',
variable_values      => vvl,
true_rules_iterator  => truehits,
maybe_rules_iterator => maybehits);
LOOP
hit := DBMS_RULE.GET_NEXT_HIT(truehits);
EXIT WHEN hit IS NULL;
DBMS_OUTPUT.PUT_LINE('Using rule '|| hit.rule_name);
ac := hit.rule_action_context;
namearray := ac.GET_ALL_NAMES;
FOR i IN 1..namearray.COUNT LOOP
name := namearray(i);
status := ac.GET_VALUE(name).GETVARCHAR2(cval);
IF (name = 'CENTER') then
DBMS_OUTPUT.PUT_LINE('Assigning problem to ' || cval);
ELSIF (name = 'ALERT') THEN
DBMS_OUTPUT.PUT_LINE('Sending alert to: '|| cval);
END IF;
END LOOP;
END LOOP;
-- Close iterators
BEGIN
DBMS_RULE.CLOSE_ITERATOR(truehits);
EXCEPTION
WHEN iter_closed THEN
NULL;
END;
BEGIN
DBMS_RULE.CLOSE_ITERATOR(maybehits);
EXCEPTION
WHEN iter_closed THEN
NULL;
END;
END;
/

/*

手順4: サンプル問題のディスパッチ

*/

EXECUTE problem_dispatch(1);
EXECUTE problem_dispatch(2);
EXECUTE problem_dispatch(3);
EXECUTE problem_dispatch(5);

/*

手順5: 環境のクリーンアップ(オプション)

supportユーザーを削除して、サンプル環境をクリーンアップできます。

*/

CONNECT SYSTEM

DROP USER support CASCADE;

/*

手順6: スプール結果のチェック

rules_stored_variables_iterative.outスプール・ファイルをチェックして、このスクリプトの完了後にすべてのアクションが正常に終了していることを確認します。

*/

SET ECHO OFF
SPOOL OFF

/*************************** END OF SCRIPT ******************************/

明示的変数内のデータに対するルールの部分評価の使用

この例では、イベントによってルールがTRUEまたはFALSEではなくMAYBEと評価された場合に部分評価を使用する方法について説明します。この例では、優先度および問題のタイプに基づいて顧客の問題を処理し、次のルールを使用して顧客の問題を処理します。

- 問題のタイプがHARDWAREのすべての問題は、サンノゼ・センターに割り当てます。

- 問題のタイプがSOFTWAREのすべての問題は、ニューヨーク・センターに割り当てます。

- 問題のタイプがNULL(不明)のすべての問題は、テキサス・センターに割り当てます。

- 優先度が1の問題については、サポート責任者にアラートが送信されます。

問題のタイプがNULLの問題は、MAYBEと評価されます。この例では、ルール・エンジン・クライアントにMAYBEルールが戻された場合に、部分評価を使用してアクションを実行します。この場合、アクションとは問題をテキサス・センターに割り当てることです。

評価コンテキストには、ディスパッチしている問題の優先度を示す、priorityという1つの明示的変数が含まれています。また、評価コンテキストには、ディスパッチしている問題のタイプ(HARDWAREまたはSOFTWARE)を示す、problem_typeという明示的変数も含まれています。これらの変数の値は、problem_dispatchプロシージャによってDBMS_RULE.EVALUATEプロシージャに渡されます。

次の手順を実行します。

1. 出力およびスプール結果の表示

2. supportユーザーの作成

3. supportユーザーへのルールに対する必要なシステム権限の付与

4. 評価コンテキストevalctxの作成

5. 問題の優先度に対応するルールの作成

6. ルール・セットrsの作成

7. ルール・セットへのルールの追加

8. データ・ディクショナリの問合せ

9. PL/SQLプロシージャproblem_dispatchの作成

10. サンプル問題のディスパッチ

11. 環境のクリーンアップ(オプション)

12. スプール結果のチェック

注意:
このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。

/************************* BEGINNING OF SCRIPT ******************************

手順1: 出力およびスプール結果の表示

SET ECHO ONを実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。

*/

SET ECHO ON
SPOOL rules_stored_variables_partial.out

/*

手順2: supportユーザーの作成

*/

CONNECT SYSTEM

ACCEPT password PROMPT 'Enter password for user: ' HIDE

GRANT ALTER SESSION, CREATE CLUSTER, CREATE DATABASE LINK, CREATE SEQUENCE,
CREATE SESSION, CREATE SYNONYM, CREATE TABLE, CREATE VIEW, CREATE INDEXTYPE,
CREATE OPERATOR, CREATE PROCEDURE, CREATE TRIGGER, CREATE TYPE
TO support IDENTIFIED BY &password;

/*

手順3: supportユーザーへのルールに対する必要なシステム権限の付与

*/

BEGIN
DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE(
privilege    => DBMS_RULE_ADM.CREATE_RULE_SET_OBJ,
grantee      => 'support',
grant_option => FALSE);
DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE(
privilege    => DBMS_RULE_ADM.CREATE_RULE_OBJ,
grantee      => 'support',
grant_option => FALSE);
DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE(
privilege    => DBMS_RULE_ADM.CREATE_EVALUATION_CONTEXT_OBJ,
grantee      => 'support',
grant_option => FALSE);
END;
/

/*

手順4: 評価コンテキストevalctxの作成

*/

CONNECT support

SET FEEDBACK 1
SET NUMWIDTH 10
SET LINESIZE 80
SET TRIMSPOOL ON
SET TAB OFF
SET PAGESIZE 100
SET SERVEROUTPUT ON
DECLARE
vt  SYS.RE$VARIABLE_TYPE_LIST;
BEGIN
vt := SYS.RE$VARIABLE_TYPE_LIST(
SYS.RE$VARIABLE_TYPE('priority', 'NUMBER', NULL, NULL),
SYS.RE$VARIABLE_TYPE('problem_type', 'VARCHAR2(30)', NULL, NULL));
DBMS_RULE_ADM.CREATE_EVALUATION_CONTEXT(
evaluation_context_name    => 'evalctx',
variable_types             => vt,
evaluation_context_comment => 'support problem definition');
end;
/

/*

手順5: 問題の優先度に対応するルールの作成

次のコードを実行すると、それぞれが1つの名前/値ペアを持つアクション・コンテキストが、各ルールに1つずつ作成されます。

*/

DECLARE
ac  SYS.RE$NV_LIST;
begin
ac := SYS.RE$NV_LIST(NULL);
ac.ADD_PAIR('ALERT', ANYDATA.CONVERTVARCHAR2('John Doe'));
DBMS_RULE_ADM.CREATE_RULE(
rule_name      => 'r1',
condition      => ':priority = 1',
action_context => ac,
rule_comment   => 'Urgent problems');
ac := sys.re$nv_list(NULL);
ac.ADD_PAIR('TRUE CENTER', ANYDATA.CONVERTVARCHAR2('San Jose'));
ac.ADD_PAIR('MAYBE CENTER', ANYDATA.CONVERTVARCHAR2('Texas'));
DBMS_RULE_ADM.CREATE_RULE(
rule_name       => 'r2',
condition       => ':problem_type = ''HARDWARE''',
action_context  => ac,
rule_comment    => 'Hardware problems');
ac := sys.re$nv_list(NULL);
ac.ADD_PAIR('TRUE CENTER', ANYDATA.CONVERTVARCHAR2('New York'));
ac.ADD_PAIR('MAYBE CENTER', ANYDATA.CONVERTVARCHAR2('Texas'));
DBMS_RULE_ADM.CREATE_RULE(
rule_name       => 'r3',
condition       => ':problem_type = ''SOFTWARE''',
action_context  => ac,
rule_comment    => 'Software problems');
END;
/

/*

手順6: ルール・セットrsの作成

*/

BEGIN
DBMS_RULE_ADM.CREATE_RULE_SET(
rule_set_name      => 'rs',
evaluation_context => 'evalctx',
rule_set_comment   => 'support rules');
END;
/

/*

手順7: ルール・セットへのルールの追加

*/

BEGIN
DBMS_RULE_ADM.ADD_RULE(
rule_name     => 'r1',
rule_set_name => 'rs');
DBMS_RULE_ADM.ADD_RULE(
rule_name     => 'r2',
rule_set_name => 'rs');
DBMS_RULE_ADM.ADD_RULE(
rule_name     => 'r3',
rule_set_name => 'rs');
END;
/

/*

手順8: データ・ディクショナリの問合せ

この時点で、前述の手順で作成した評価コンテキスト、ルールおよびルール・セットを表示できます。

*/

COLUMN EVALUATION_CONTEXT_NAME HEADING 'Eval Context Name' FORMAT A30
COLUMN EVALUATION_CONTEXT_COMMENT HEADING 'Eval Context Comment' FORMAT A40

SELECT EVALUATION_CONTEXT_NAME, EVALUATION_CONTEXT_COMMENT
FROM USER_EVALUATION_CONTEXTS
ORDER BY EVALUATION_CONTEXT_NAME;

SET LONGCHUNKSIZE 4000
SET LONG 4000
COLUMN RULE_NAME HEADING 'Rule|Name' FORMAT A5
COLUMN RULE_CONDITION HEADING 'Rule Condition' FORMAT A35
COLUMN ACTION_CONTEXT_NAME HEADING 'Action|Context|Name' FORMAT A10
COLUMN ACTION_CONTEXT_VALUE HEADING 'Action|Context|Value' FORMAT A10

SELECT RULE_NAME,
RULE_CONDITION,
AC.NVN_NAME ACTION_CONTEXT_NAME,
AC.NVN_VALUE.ACCESSVARCHAR2() ACTION_CONTEXT_VALUE
FROM USER_RULES R, TABLE(R.RULE_ACTION_CONTEXT.ACTX_LIST) AC
ORDER BY RULE_NAME;

COLUMN RULE_SET_NAME HEADING 'Rule Set Name' FORMAT A20
COLUMN RULE_SET_EVAL_CONTEXT_OWNER HEADING 'Eval Context|Owner' FORMAT A12
COLUMN RULE_SET_EVAL_CONTEXT_NAME HEADING 'Eval Context Name' FORMAT A25
COLUMN RULE_SET_COMMENT HEADING 'Rule Set|Comment' FORMAT A15

SELECT RULE_SET_NAME,
RULE_SET_EVAL_CONTEXT_OWNER,
RULE_SET_EVAL_CONTEXT_NAME,
RULE_SET_COMMENT
FROM USER_RULE_SETS
ORDER BY RULE_SET_NAME;

/*

手順9: PL/SQLプロシージャproblem_dispatchの作成

*/

CREATE OR REPLACE PROCEDURE problem_dispatch (priority     NUMBER,
problem_type VARCHAR2 := NULL)
IS
vvl       SYS.RE$VARIABLE_VALUE_LIST;
truehits  SYS.RE$RULE_HIT_LIST;
maybehits SYS.RE$RULE_HIT_LIST;
ac        SYS.RE$NV_LIST;
namearray SYS.RE$NAME_ARRAY;
name      VARCHAR2(30);
cval      VARCHAR2(100);
rnum      INTEGER;
i         INTEGER;
status    PLS_INTEGER;
BEGIN
IF (problem_type IS NULL) THEN
vvl  := SYS.RE$VARIABLE_VALUE_LIST(
SYS.RE$VARIABLE_VALUE('priority',
ANYDATA.CONVERTNUMBER(priority)));
ELSE
vvl  := SYS.RE$VARIABLE_VALUE_LIST(
SYS.RE$VARIABLE_VALUE('priority',
ANYDATA.CONVERTNUMBER(priority)),
SYS.RE$VARIABLE_VALUE('problem_type',
ANYDATA.CONVERTVARCHAR2(problem_type)));
END IF;
truehits := SYS.RE$RULE_HIT_LIST();
maybehits := SYS.RE$RULE_HIT_LIST();
DBMS_RULE.EVALUATE(
rule_set_name        => 'support.rs',
evaluation_context   => 'evalctx',
variable_values      => vvl,
true_rules           => truehits,
maybe_rules          => maybehits);
FOR rnum IN 1..truehits.COUNT LOOP
DBMS_OUTPUT.PUT_LINE('Using rule '|| truehits(rnum).rule_name);
ac := truehits(rnum).rule_action_context;
namearray := ac.GET_ALL_NAMES;
FOR i IN 1..namearray.count LOOP
name := namearray(i);
status := ac.GET_VALUE(name).GETVARCHAR2(cval);
IF (name = 'TRUE CENTER') then
DBMS_OUTPUT.PUT_LINE('Assigning problem to ' || cval);
ELSIF (name = 'ALERT') THEN
DBMS_OUTPUT.PUT_LINE('Sending alert to: '|| cval);
END IF;
END LOOP;
END LOOP;
FOR rnum IN 1..maybehits.COUNT LOOP
DBMS_OUTPUT.PUT_LINE('Using rule '|| maybehits(rnum).rule_name);
ac := maybehits(rnum).rule_action_context;
namearray := ac.GET_ALL_NAMES;
FOR i IN 1..namearray.count loop
name := namearray(i);
status := ac.GET_VALUE(name).GETVARCHAR2(cval);
IF (name = 'MAYBE CENTER') then
DBMS_OUTPUT.PUT_LINE('Assigning problem to ' || cval);
END IF;
END LOOP;
END LOOP;
END;
/

/*

手順10: サンプル問題のディスパッチ

この手順での最初の問題のディスパッチでは、部分評価を使用し、部分評価に基づいてアクションを実行します。具体的には、最初の問題のディスパッチでは、priorityを1、problem_typeをNULLに指定します。この場合、ルール・エンジンによってイベントのMAYBEルールが戻され、problem_dispatchプロシージャによって問題がテキサス・センターに割り当てられます。

2番目および3番目の問題のディスパッチでは、部分評価を使用しません。これらの各問題についてルールがTRUEかどうかが評価され、それに応じてproblem_dispatchプロシージャによって問題が割り当てられます。

*/

EXECUTE problem_dispatch(1, NULL);
EXECUTE problem_dispatch(2, 'HARDWARE');
EXECUTE problem_dispatch(3, 'SOFTWARE');

/*

手順11: 環境のクリーンアップ(オプション)

supportユーザーを削除して、サンプル環境をクリーンアップできます。

*/

CONNECT SYSTEM

DROP USER support CASCADE;

/*

手順12: スプール結果のチェック

rules_stored_variables_partial.outスプール・ファイルをチェックして、このスクリプトの完了後にすべてのアクションが正常に終了していることを確認します。

*/

SET ECHO OFF
SPOOL OFF

/*************************** END OF SCRIPT ******************************/

表に格納されたデータに対するルールの使用

この例では、ルールを使用して、表に格納されたデータを評価する方法について説明します。この例は、「明示的変数に格納された表以外のデータに対するルールの使用」で説明した例に類似しています。いずれの例でも、アプリケーションは優先度に基づいて顧客の問題をルーティングします。ただし、この例では、問題は変数ではなく表に格納されます。

アプリケーションでは、supportスキーマのproblems表が使用され、この表に顧客の問題が挿入されます。この例では、次のルールを使用して顧客の問題を処理します。

- 優先度が2より大きいすべての問題は、サンノゼ・センターに割り当てます。

- 優先度が2以下のすべての問題は、ニューヨーク・センターに割り当てます。

- 優先度が1の問題については、サポート責任者にアラートが送信されます。

評価コンテキストは、problems表で構成されています。ルーティングしている問題に対応する、表の関連する行は、表の値としてDBMS_RULE.EVALUATEプロシージャに渡されます。

次の手順を実行します。

1. 出力およびスプール結果の表示

2. supportユーザーの作成

3. supportユーザーへのルールに対する必要なシステム権限の付与

4. problems表の作成

5. 評価コンテキストevalctxの作成

6. 問題の優先度に対応するルールの作成

7. ルール・セットrsの作成

8. ルール・セットへのルールの追加

9. PL/SQLプロシージャproblem_dispatchの作成

10. 問題のロギング

11. スプール結果のチェック

注意:
このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。

/************************* BEGINNING OF SCRIPT ******************************

手順1: 出力およびスプール結果の表示

SET ECHO ONを実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。

*/

SET ECHO ON
SPOOL rules_table.out

/*

手順2: supportユーザーの作成

*/

CONNECT SYSTEM

CREATE TABLESPACE support_tbs1 DATAFILE 'support_tbs1.dbf'
SIZE 5M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;

ACCEPT password PROMPT 'Enter password for user: ' HIDE

CREATE USER support
IDENTIFIED BY &password
DEFAULT TABLESPACE support_tbs1
QUOTA UNLIMITED ON support_tbs1;

GRANT ALTER SESSION, CREATE CLUSTER, CREATE DATABASE LINK, CREATE SEQUENCE,
CREATE SESSION, CREATE SYNONYM, CREATE TABLE, CREATE VIEW, CREATE INDEXTYPE,
CREATE OPERATOR, CREATE PROCEDURE, CREATE TRIGGER, CREATE TYPE
TO support;

/*

手順3: supportユーザーへのルールに対する必要なシステム権限の付与

*/

BEGIN
DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE(
privilege    => DBMS_RULE_ADM.CREATE_RULE_SET_OBJ,
grantee      => 'support',
grant_option => FALSE);
DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE(
privilege    => DBMS_RULE_ADM.CREATE_RULE_OBJ,
grantee      => 'support',
grant_option => FALSE);
DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE(
privilege    => DBMS_RULE_ADM.CREATE_EVALUATION_CONTEXT_OBJ,
grantee      => 'support',
grant_option => FALSE);
END;
/

/*

手順4: problems表の作成

*/

CONNECT support

SET FEEDBACK 1
SET NUMWIDTH 10
SET LINESIZE 80
SET TRIMSPOOL ON
SET TAB OFF
SET PAGESIZE 100
SET SERVEROUTPUT ON

CREATE TABLE problems(
probid          NUMBER PRIMARY KEY,
custid          NUMBER,
priority        NUMBER,
description     VARCHAR2(4000),
center          VARCHAR2(100));

/*

手順5: 評価コンテキストevalctxの作成

*/

DECLARE
ta  SYS.RE$TABLE_ALIAS_LIST;
BEGIN
ta := SYS.RE$TABLE_ALIAS_LIST(SYS.RE$TABLE_ALIAS('prob', 'problems'));
DBMS_RULE_ADM.CREATE_EVALUATION_CONTEXT(
evaluation_context_name    => 'evalctx',
table_aliases              => ta,
evaluation_context_comment => 'support problem definition');
END;
/

/*

手順6: 問題の優先度に対応するルールの作成

次のコードを実行すると、それぞれが1つの名前/値ペアを持つアクション・コンテキストが、各ルールに1つずつ作成されます。

*/

DECLARE
ac  SYS.RE$NV_LIST;
BEGIN
ac := SYS.RE$NV_LIST(NULL);
ac.ADD_PAIR('CENTER', ANYDATA.CONVERTVARCHAR2('San Jose'));
DBMS_RULE_ADM.CREATE_RULE(
rule_name      => 'r1',
condition      => 'prob.priority > 2',
action_context => ac,
rule_comment   => 'Low priority problems');
ac := SYS.RE$NV_LIST(NULL);
ac.ADD_PAIR('CENTER', ANYDATA.CONVERTVARCHAR2('New York'));
DBMS_RULE_ADM.CREATE_RULE(
rule_name      => 'r2',
condition      => 'prob.priority <= 2',
action_context => ac,
rule_comment   => 'High priority problems');
ac := sys.RE$NV_LIST(NULL);
ac.ADD_PAIR('ALERT', ANYDATA.CONVERTVARCHAR2('John Doe'));
DBMS_RULE_ADM.CREATE_RULE(
rule_name      => 'r3',
condition      => 'prob.priority = 1',
action_context => ac,
rule_comment   => 'Urgent problems');
END;
/

/*

手順7: ルール・セットrsの作成

*/

BEGIN
DBMS_RULE_ADM.CREATE_RULE_SET(
rule_set_name      => 'rs',
evaluation_context => 'evalctx',
rule_set_comment   => 'support rules');
END;
/

/*

手順8: ルール・セットへのルールの追加

*/

BEGIN
DBMS_RULE_ADM.ADD_RULE(
rule_name     => 'r1',
rule_set_name => 'rs');
DBMS_RULE_ADM.ADD_RULE(
rule_name     => 'r2',
rule_set_name => 'rs');
DBMS_RULE_ADM.ADD_RULE(
rule_name     => 'r3',
rule_set_name => 'rs');
END;
/

/*

手順9: PL/SQLプロシージャproblem_dispatchの作成

*/

CREATE OR REPLACE PROCEDURE problem_dispatch
IS
cursor c IS SELECT probid, rowid FROM problems WHERE center IS NULL;
tv        SYS.RE$TABLE_VALUE;
tvl       SYS.RE$TABLE_VALUE_LIST;
truehits  SYS.RE$RULE_HIT_LIST;
maybehits SYS.RE$RULE_HIT_LIST;
ac        SYS.RE$NV_LIST;
namearray SYS.RE$NAME_ARRAY;
name      VARCHAR2(30);
cval      VARCHAR2(100);
rnum      INTEGER;
i         INTEGER;
status    PLS_INTEGER;
BEGIN
FOR r IN c LOOP
tv  := SYS.RE$TABLE_VALUE('prob', rowidtochar(r.rowid));
tvl := SYS.RE$TABLE_VALUE_LIST(tv);
truehits := SYS.RE$RULE_HIT_LIST();
maybehits := SYS.RE$RULE_HIT_LIST();
DBMS_RULE.EVALUATE(
rule_set_name        => 'support.rs',
evaluation_context   => 'evalctx',
table_values         => tvl,
true_rules           => truehits,
maybe_rules          => maybehits);
FOR rnum IN 1..truehits.COUNT LOOP
DBMS_OUTPUT.PUT_LINE('Using rule '|| truehits(rnum).rule_name);
ac := truehits(rnum).rule_action_context;
namearray := ac.GET_ALL_NAMES;
FOR i IN 1..namearray.COUNT LOOP
name := namearray(i);
status := ac.GET_VALUE(name).GETVARCHAR2(cval);
IF (name = 'CENTER') THEN
UPDATE PROBLEMS SET center = cval WHERE rowid = r.rowid;
DBMS_OUTPUT.PUT_LINE('Assigning '|| r.probid || ' to ' || cval);
ELSIF (name = 'ALERT') THEN
DBMS_OUTPUT.PUT_LINE('Alert: '|| cval || ' Problem:' || r.probid);
END IF;
END LOOP;
END LOOP;
END LOOP;
END;
/

/*

手順10: 問題のロギング

*/

INSERT INTO problems(probid, custid, priority, description)
VALUES(10101, 11, 1, 'no dial tone');

INSERT INTO problems(probid, custid, priority, description)
VALUES(10102, 21, 2, 'noise on local calls');

INSERT INTO problems(probid, custid, priority, description)
VALUES(10103, 31, 3, 'noise on long distance calls');

COMMIT;

/*

手順11: スプール結果のチェック

rules_table.outスプール・ファイルをチェックして、このスクリプトの完了後にすべてのアクションが正常に終了していることを確認します。

*/

SET ECHO OFF
SPOOL OFF

/*************************** END OF SCRIPT ******************************/

関連項目:
この例でログに記録された問題をディスパッチし、問題のディスパッチの結果をチェックする手順については、「問題のディスパッチおよび表の例の結果のチェック」を参照してください。

明示的変数と表データの両方に対するルールの使用

この例では、ルールを使用して、明示的変数および表に格納されたデータを評価する方法について説明します。アプリケーションでは、supportスキーマのproblems表が使用され、この表に顧客の問題が挿入されます。この例では、次のルールを使用して顧客の問題を処理します。

- 優先度が2より大きいすべての問題は、サンノゼ・センターに割り当てます。

- 優先度が2のすべての問題は、ニューヨーク・センターに割り当てます。

- 優先度が1のすべての問題は、午前8時から午後8時まではタンパ・センターに割り当てます。

- 優先度が1のすべての問題は、午後8時から午前8時まではバンガロール・センターに割り当てます。

- 優先度が1の問題については、サポート責任者にアラートが送信されます。

評価コンテキストは、problems表で構成されています。ルーティングしている問題に対応する、表の関連する行は、表の値としてDBMS_RULE.EVALUATEプロシージャに渡されます。

この例の一部のルールは、current_timeという明示的変数として表される現在の時刻を参照します。現在の時刻は、評価コンテキスト内の追加データとして処理されます。現在の時刻は、次の理由のために変数として表されます。

- 頻繁な更新が必要になるため、現在の時刻を表に格納することは実践的ではありません。

- 現在の時刻には、その時刻を必要とするすべてのルールにSYSDATEへのコールを挿入することによってアクセスできます。ただし、これによって同じSQLファンクションSYSDATEが繰り返しコールされ、ルールの評価が遅くなる場合があります。異なるルールに値が異なる現在の時刻が含まれることによって、不適切な動作が発生する場合があります。

次の手順を実行します。

1. 出力およびスプール結果の表示

2. supportユーザーの作成

3. supportユーザーへのルールに対する必要なシステム権限の付与

4. problems表の作成

5. 評価コンテキストevalctxの作成

6. 問題の優先度に対応するルールの作成

7. ルール・セットrsの作成

8. ルール・セットへのルールの追加

9. PL/SQLプロシージャproblem_dispatchの作成

10. 問題のロギング

11. スプール結果のチェック

注意:
このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。

/************************* BEGINNING OF SCRIPT ******************************

手順1: 出力およびスプール結果の表示

SET ECHO ONを実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。

*/

SET ECHO ON
SPOOL rules_var_tab.out

/*

手順2: supportユーザーの作成

*/

CONNECT SYSTEM

CREATE TABLESPACE support_tbs2 DATAFILE 'support_tbs2.dbf'
SIZE 5M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;

ACCEPT password PROMPT 'Enter password for user: ' HIDE

CREATE USER support
IDENTIFIED BY &password
DEFAULT TABLESPACE support_tbs2
QUOTA UNLIMITED ON support_tbs2;

GRANT ALTER SESSION, CREATE CLUSTER, CREATE DATABASE LINK, CREATE SEQUENCE,
CREATE SESSION, CREATE SYNONYM, CREATE TABLE, CREATE VIEW, CREATE INDEXTYPE,
CREATE OPERATOR, CREATE PROCEDURE, CREATE TRIGGER, CREATE TYPE
TO support;

/*

手順3: supportユーザーへのルールに対する必要なシステム権限の付与

*/

BEGIN
DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE(
privilege    => DBMS_RULE_ADM.CREATE_RULE_SET_OBJ,
grantee      => 'support',
grant_option => FALSE);
DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE(
privilege    => DBMS_RULE_ADM.CREATE_RULE_OBJ,
grantee      => 'support',
grant_option => FALSE);
DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE(
privilege    => DBMS_RULE_ADM.CREATE_EVALUATION_CONTEXT_OBJ,
grantee      => 'support',
grant_option => FALSE);
END;
/

/*

手順4: problems表の作成

*/

CONNECT support

SET FEEDBACK 1
SET NUMWIDTH 10
SET LINESIZE 80
SET TRIMSPOOL ON
SET TAB OFF
SET PAGESIZE 100
SET SERVEROUTPUT ON

CREATE TABLE problems(
probid          NUMBER PRIMARY KEY,
custid          NUMBER,
priority        NUMBER,
description     VARCHAR2(4000),
center          VARCHAR2(100));

/*

手順5: 評価コンテキストevalctxの作成

*/

DECLARE
ta SYS.RE$TABLE_ALIAS_LIST;
vt SYS.RE$VARIABLE_TYPE_LIST;
BEGIN
ta := SYS.RE$TABLE_ALIAS_LIST(SYS.RE$TABLE_ALIAS('prob', 'problems'));
vt := SYS.RE$VARIABLE_TYPE_LIST(
SYS.RE$VARIABLE_TYPE('current_time', 'DATE', NULL, NULL));
DBMS_RULE_ADM.CREATE_EVALUATION_CONTEXT(
evaluation_context_name    => 'evalctx',
table_aliases              => ta,
variable_types             => vt,
evaluation_context_comment => 'support problem definition');
END;
/

/*

手順6: 問題の優先度に対応するルールの作成

次のコードを実行すると、それぞれが1つの名前/値ペアを持つアクション・コンテキストが、各ルールに1つずつ作成されます。

*/

DECLARE
ac SYS.RE$NV_LIST;
BEGIN
ac := SYS.RE$NV_LIST(NULL);
ac.ADD_PAIR('CENTER', ANYDATA.CONVERTVARCHAR2('San Jose'));
DBMS_RULE_ADM.CREATE_RULE(
rule_name      => 'r1',
condition      => 'prob.priority > 2',
action_context => ac,
rule_comment   => 'Low priority problems');
ac := SYS.RE$NV_LIST(NULL);
ac.ADD_PAIR('CENTER', ANYDATA.CONVERTVARCHAR2('New York'));
DBMS_RULE_ADM.CREATE_RULE(
rule_name      => 'r2',
condition      => 'prob.priority = 2',
action_context => ac,
rule_comment   => 'High priority problems');
ac := SYS.RE$NV_LIST(NULL);
ac.ADD_PAIR('ALERT', ANYDATA.CONVERTVARCHAR2('John Doe'));
DBMS_RULE_ADM.CREATE_RULE(
rule_name      => 'r3',
condition      => 'prob.priority = 1',
action_context => ac,
rule_comment   => 'Urgent problems');
ac := SYS.RE$NV_LIST(NULL);
ac.ADD_PAIR('CENTER', ANYDATA.CONVERTVARCHAR2('Tampa'));
DBMS_RULE_ADM.CREATE_RULE(
rule_name => 'r4',
condition => '(prob.priority = 1) and ' ||
'(TO_NUMBER(TO_CHAR(:current_time, ''HH24'')) >= 8) and ' ||
'(TO_NUMBER(TO_CHAR(:current_time, ''HH24'')) <= 20)',
action_context => ac,
rule_comment => 'Urgent daytime problems');
ac := sys.RE$NV_LIST(NULL);
ac.add_pair('CENTER', ANYDATA.CONVERTVARCHAR2('Bangalore'));
DBMS_RULE_ADM.CREATE_RULE(
rule_name => 'r5',
condition => '(prob.priority = 1) and ' ||
'((TO_NUMBER(TO_CHAR(:current_time, ''HH24'')) < 8) or ' ||
' (TO_NUMBER(TO_CHAR(:current_time, ''HH24'')) > 20))',
action_context => ac,
rule_comment => 'Urgent nighttime problems');
END;
/

/*

手順7: ルール・セットrsの作成

*/

BEGIN
DBMS_RULE_ADM.CREATE_RULE_SET(
rule_set_name      => 'rs',
evaluation_context => 'evalctx',
rule_set_comment   => 'support rules');
END;
/

/*

手順8: ルール・セットへのルールの追加

*/

BEGIN
DBMS_RULE_ADM.ADD_RULE(
rule_name     => 'r1',
rule_set_name => 'rs');
DBMS_RULE_ADM.ADD_RULE(
rule_name     => 'r2',
rule_set_name => 'rs');
DBMS_RULE_ADM.ADD_RULE(
rule_name     => 'r3',
rule_set_name => 'rs');
DBMS_RULE_ADM.ADD_RULE(
rule_name     => 'r4',
rule_set_name => 'rs');
DBMS_RULE_ADM.ADD_RULE(
rule_name     => 'r5',
rule_set_name => 'rs');
END;
/

/*

手順9: PL/SQLプロシージャproblem_dispatchの作成

*/

CREATE OR REPLACE PROCEDURE problem_dispatch
IS
cursor c  is SELECT probid, rowid FROM PROBLEMS WHERE center IS NULL;
tv        SYS.RE$TABLE_VALUE;
tvl       SYS.RE$TABLE_VALUE_LIST;
vv1       SYS.RE$VARIABLE_VALUE;
vvl       SYS.RE$VARIABLE_VALUE_LIST;
truehits  SYS.RE$RULE_HIT_LIST;
maybehits SYS.RE$RULE_HIT_LIST;
ac        SYS.RE$NV_LIST;
namearray SYS.RE$NAME_ARRAY;
name      VARCHAR2(30);
cval      VARCHAR2(100);
rnum      INTEGER;
i         INTEGER;
status    PLS_INTEGER;
BEGIN
FOR r IN c LOOP
tv  := sYS.RE$TABLE_VALUE('prob', ROWIDTOCHAR(r.rowid));
tvl := SYS.RE$TABLE_VALUE_LIST(tv);
vv1 := SYS.RE$VARIABLE_VALUE('current_time',
ANYDATA.CONVERTDATE(SYSDATE));
vvl := SYS.RE$VARIABLE_VALUE_LIST(vv1);
truehits := SYS.RE$RULE_HIT_LIST();
maybehits := SYS.RE$RULE_HIT_LIST();
DBMS_RULE.EVALUATE(
rule_set_name        => 'support.rs',
evaluation_context   => 'evalctx',
table_values         => tvl,
variable_values      => vvl,
true_rules           => truehits,
maybe_rules          => maybehits);
FOR rnum IN 1..truehits.COUNT loop
DBMS_OUTPUT.PUT_LINE('Using rule '|| truehits(rnum).rule_name);
ac := truehits(rnum).rule_action_context;
namearray := ac.GET_ALL_NAMES;
FOR i in 1..namearray.COUNT LOOP
name := namearray(i);
status := ac.GET_VALUE(name).GETVARCHAR2(cval);
IF (name = 'CENTER') THEN
UPDATE problems SET center = cval
WHERE rowid = r.rowid;
DBMS_OUTPUT.PUT_LINE('Assigning '|| r.probid || ' to ' || cval);
ELSIF (name = 'ALERT') THEN
DBMS_OUTPUT.PUT_LINE('Alert: '|| cval || ' Problem:' || r.probid);
END IF;
END LOOP;
END LOOP;
END LOOP;
END;
/

/*

手順10: 問題のロギング

*/

INSERT INTO problems(probid, custid, priority, description)
VALUES(10201, 12, 1, 'no dial tone');

INSERT INTO problems(probid, custid, priority, description)
VALUES(10202, 22, 2, 'noise on local calls');

INSERT INTO PROBLEMS(probid, custid, priority, description)
VALUES(10203, 32, 3, 'noise on long distance calls');

COMMIT;

/*

手順11: スプール結果のチェック

rules_var_tab.outスプール・ファイルをチェックして、このスクリプトの完了後にすべてのアクションが正常に終了していることを確認します。

*/

SET ECHO OFF
SPOOL OFF

/*************************** END OF SCRIPT ******************************/

関連項目:
この例でログに記録された問題をディスパッチし、問題のディスパッチの結果をチェックする手順については、「問題のディスパッチおよび表の例の結果のチェック」を参照してください。

暗黙的変数および表データに対するルールの使用

この例では、ルールを使用して、暗黙的変数および表に格納されたデータを評価する方法について説明します。アプリケーションでは、supportスキーマのproblems表が使用され、この表に顧客の問題が挿入されます。この例では、次のルールを使用して顧客の問題を処理します。

- 優先度が2より大きいすべての問題は、サンノゼ・センターに割り当てます。

- 優先度が2のすべての問題は、ニューヨーク・センターに割り当てます。

- 優先度が1のすべての問題は、午前8時から午後8時まではタンパ・センターに割り当てます。

- 優先度が1のすべての問題は、午後8時から午前8時まではバンガロール・センターに割り当てます。

- 優先度が1の問題については、サポート責任者にアラートが送信されます。

評価コンテキストは、problems表で構成されています。ルーティングしている問題に対応する、表の関連する行は、表の値としてDBMS_RULE.EVALUATEプロシージャに渡されます。

「明示的変数と表データの両方に対するルールの使用」で説明した例と同様に、現在の時刻は、current_timeという変数として表されます。ただし、この変数値は、評価中にコール元によって指定されません。つまり、この例では、current_timeは暗黙的変数です。timefuncというPL/SQLファンクションがcurrent_timeに指定され、このファンクションは、その値を取得するために評価中に1回コールされます。

次のいずれかの条件に該当する場合は、暗黙的変数の使用が他の場合にも役立つ可能性があります。

- コール元が変数値に対するアクセス権を持っていない。

- 変数がルールで頻繁に参照されない。変数は暗黙的であるため、必要な場合にのみその値を取得できます。すべての評価で値を渡す必要はありません。

次の手順を実行します。

1. 出力およびスプール結果の表示

2. supportユーザーの作成

3. supportユーザーへのルールに対する必要なシステム権限の付与

4. problems表の作成

5. current_timeの値を戻すtimefuncファンクションの作成

6. 評価コンテキストevalctxの作成

7. 問題の優先度に対応するルールの作成

8. ルール・セットrsの作成

9. ルール・セットへのルールの追加

10. PL/SQLプロシージャproblem_dispatchの作成

11. 問題のロギング

12. スプール結果のチェック

注意:
このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。

/************************* BEGINNING OF SCRIPT ******************************

手順1: 出力およびスプール結果の表示

SET ECHO ONを実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。

*/

SET ECHO ON
SPOOL rules_implicit_var.out

/*

手順2: supportユーザーの作成

*/

CONNECT SYSTEM

CREATE TABLESPACE support_tbs3 DATAFILE 'support_tbs3.dbf'
SIZE 5M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;

ACCEPT password PROMPT 'Enter password for user: ' HIDE

CREATE USER support
IDENTIFIED BY &password
DEFAULT TABLESPACE support_tbs3
QUOTA UNLIMITED ON support_tbs3;

GRANT ALTER SESSION, CREATE CLUSTER, CREATE DATABASE LINK, CREATE SEQUENCE,
CREATE SESSION, CREATE SYNONYM, CREATE TABLE, CREATE VIEW, CREATE INDEXTYPE,
CREATE OPERATOR, CREATE PROCEDURE, CREATE TRIGGER, CREATE TYPE
TO support;

/*

手順3: supportユーザーへのルールに対する必要なシステム権限の付与

*/

BEGIN
DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE(
privilege    => DBMS_RULE_ADM.CREATE_RULE_SET_OBJ,
grantee      => 'support',
grant_option => FALSE);
DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE(
privilege    => DBMS_RULE_ADM.CREATE_RULE_OBJ,
grantee      => 'support',
grant_option => FALSE);
DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE(
privilege    => DBMS_RULE_ADM.CREATE_EVALUATION_CONTEXT_OBJ,
grantee      => 'support',
grant_option => FALSE);
END;
/

/*

手順4: problems表の作成

*/

CONNECT support

SET FEEDBACK 1
SET NUMWIDTH 10
SET LINESIZE 80
SET TRIMSPOOL ON
SET TAB OFF
SET PAGESIZE 100
SET SERVEROUTPUT ON

CREATE TABLE problems(
probid          NUMBER PRIMARY KEY,
custid          NUMBER,
priority        NUMBER,
description     VARCHAR2(4000),
center          VARCHAR2(100));

/*

手順5: current_timeの値を戻すtimefuncファンクションの作成

*/

CREATE OR REPLACE FUNCTION timefunc(
eco    VARCHAR2,
ecn    VARCHAR2,
var    VARCHAR2,
evctx  SYS.RE$NV_LIST)
RETURN SYS.RE$VARIABLE_VALUE
IS
BEGIN
IF (var = 'CURRENT_TIME') THEN
RETURN(SYS.RE$VARIABLE_VALUE('current_time',
ANYDATA.CONVERTDATE(SYSDATE)));
ELSE
RETURN(NULL);
END IF;
END;
/

/*

手順6: 評価コンテキストevalctxの作成

*/

DECLARE
ta SYS.RE$TABLE_ALIAS_LIST;
vt SYS.RE$VARIABLE_TYPE_LIST;
BEGIN
ta := SYS.RE$TABLE_ALIAS_LIST(SYS.RE$TABLE_ALIAS('prob', 'problems'));
vt := SYS.RE$VARIABLE_TYPE_LIST(
SYS.RE$VARIABLE_TYPE('current_time', 'DATE', 'timefunc', NULL));
DBMS_RULE_ADM.CREATE_EVALUATION_CONTEXT(
evaluation_context_name    => 'evalctx',
table_aliases              => ta,
variable_types             => vt,
evaluation_context_comment => 'support problem definition');
END;
/

/*

手順7: 問題の優先度に対応するルールの作成

次のコードを実行すると、それぞれが1つの名前/値ペアを持つアクション・コンテキストが、各ルールに1つずつ作成されます。

*/

DECLARE
ac SYS.RE$NV_LIST;
BEGIN
ac := SYS.RE$NV_LIST(NULL);
ac.ADD_PAIR('CENTER', ANYDATA.CONVERTVARCHAR2('San Jose'));
DBMS_RULE_ADM.CREATE_RULE(
rule_name      => 'r1',
condition      => 'prob.priority > 2',
action_context => ac,
rule_comment   => 'Low priority problems');
ac := SYS.RE$NV_LIST(NULL);
ac.ADD_PAIR('CENTER', ANYDATA.CONVERTVARCHAR2('New York'));
DBMS_RULE_ADM.CREATE_RULE(
rule_name      => 'r2',
condition      => 'prob.priority = 2',
action_context => ac,
rule_comment   => 'High priority problems');
ac := SYS.RE$NV_LIST(NULL);
ac.ADD_PAIR('ALERT', ANYDATA.CONVERTVARCHAR2('John Doe'));
DBMS_RULE_ADM.CREATE_RULE(
rule_name      => 'r3',
condition      => 'prob.priority = 1',
action_context => ac,
rule_comment   => 'Urgent problems');
ac := SYS.RE$NV_LIST(NULL);
ac.ADD_PAIR('CENTER', ANYDATA.CONVERTVARCHAR2('Tampa'));
DBMS_RULE_ADM.CREATE_RULE(
rule_name => 'r4',
condition => '(prob.priority = 1) and ' ||
'(TO_NUMBER(TO_CHAR(:current_time, ''HH24'')) >= 8) and ' ||
'(TO_NUMBER(TO_CHAR(:current_time, ''HH24'')) <= 20)',
action_context => ac,
rule_comment   => 'Urgent daytime problems');
ac := SYS.RE$NV_LIST(NULL);
ac.add_pair('CENTER', ANYDATA.CONVERTVARCHAR2('Bangalore'));
DBMS_RULE_ADM.CREATE_RULE(
rule_name => 'r5',
condition => '(prob.priority = 1) and ' ||
'((TO_NUMBER(TO_CHAR(:current_time, ''HH24'')) < 8) or ' ||
' (TO_NUMBER(TO_CHAR(:current_time, ''HH24'')) > 20))',
action_context => ac,
rule_comment => 'Urgent nighttime problems');
END;
/

/*

手順8: ルール・セットrsの作成

*/

BEGIN
DBMS_RULE_ADM.CREATE_RULE_SET(
rule_set_name      => 'rs',
evaluation_context => 'evalctx',
rule_set_comment   => 'support rules');
END;
/

/*

手順9: ルール・セットへのルールの追加

*/

BEGIN
DBMS_RULE_ADM.ADD_RULE(
rule_name     => 'r1',
rule_set_name => 'rs');
DBMS_RULE_ADM.ADD_RULE(
rule_name     => 'r2',
rule_set_name => 'rs');
DBMS_RULE_ADM.ADD_RULE(
rule_name     => 'r3',
rule_set_name => 'rs');
DBMS_RULE_ADM.ADD_RULE(
rule_name     => 'r4',
rule_set_name => 'rs');
DBMS_RULE_ADM.ADD_RULE(
rule_name     => 'r5',
rule_set_name => 'rs');
END;
/

/*

手順10: PL/SQLプロシージャproblem_dispatchの作成

*/

CREATE OR REPLACE PROCEDURE problem_dispatch
IS
cursor c  IS SELECT probid, rowid FROM problems WHERE center IS NULL;
tv        SYS.RE$TABLE_VALUE;
tvl       SYS.RE$TABLE_VALUE_LIST;
truehits  SYS.RE$RULE_HIT_LIST;
maybehits SYS.RE$RULE_HIT_LIST;
ac        SYS.RE$NV_LIST;
namearray SYS.RE$NAME_ARRAY;
name      VARCHAR2(30);
cval      VARCHAR2(100);
rnum      INTEGER;
i         INTEGER;
status    PLS_INTEGER;
BEGIN
FOR r IN c LOOP
tv  := SYS.RE$TABLE_VALUE('prob', rowidtochar(r.rowid));
tvl := SYS.RE$TABLE_VALUE_LIST(tv);
truehits := SYS.RE$RULE_HIT_LIST();
maybehits := SYS.RE$RULE_HIT_LIST();
DBMS_RULE.EVALUATE(
rule_set_name        => 'support.rs',
evaluation_context   => 'evalctx',
table_values         => tvl,
true_rules           => truehits,
maybe_rules          => maybehits);
FOR rnum IN 1..truehits.COUNT LOOP
DBMS_OUTPUT.PUT_LINE('Using rule '|| truehits(rnum).rule_name);
ac := truehits(rnum).rule_action_context;
namearray := ac.GET_ALL_NAMES;
FOR i IN 1..namearray.COUNT LOOP
name := namearray(i);
status := ac.GET_VALUE(name).GETVARCHAR2(cval);
IF (name = 'CENTER') THEN
UPDATE problems SET center = cval
WHERE rowid = r.rowid;
DBMS_OUTPUT.PUT_LINE('Assigning '|| r.probid || ' to ' || cval);
ELSIF (name = 'ALERT') THEN
DBMS_OUTPUT.PUT_LINE('Alert: '|| cval || ' Problem:' || r.probid);
END IF;
END LOOP;
END LOOP;
END LOOP;
END;
/

/*

手順11: 問題のロギング

*/

INSERT INTO problems(probid, custid, priority, description)
VALUES(10301, 13, 1, 'no dial tone');

INSERT INTO problems(probid, custid, priority, description)
VALUES(10302, 23, 2, 'noise on local calls');

INSERT INTO problems(probid, custid, priority, description)
VALUES(10303, 33, 3, 'noise on long distance calls');

COMMIT;

/*

手順12: スプール結果のチェック

rules_implicit_var.outスプール・ファイルをチェックして、このスクリプトの完了後にすべてのアクションが正常に終了していることを確認します。

*/

SET ECHO OFF
SPOOL OFF

/*************************** END OF SCRIPT ******************************/

関連項目:
この例でログに記録された問題をディスパッチし、問題のディスパッチの結果をチェックする手順については、「問題のディスパッチおよび表の例の結果のチェック」を参照してください。

イベント・コンテキストおよび暗黙的変数のルールとの併用

イベント・コンテキストは、イベントに関する情報を含む名前/値ペアを持つSYS.RE$NV_LIST型の配列です。このオプションの情報がルール・エンジンによって直接使用または解析されることはありません。かわりに、評価ファンクション、変数値のファンクション(暗黙的変数用)、変数メソッド・ファンクションなど、クライアントのコールバックに渡されます。

この例では、すべての顧客が主要担当者を持っていると想定しています。この例の目標は、顧客によってレポートされた問題を、顧客の主要担当者が属するサポート・センターに割り当てることです。顧客名はイベント・コンテキストに渡されます。

この例では、ルールとともにイベント・コンテキスト使用して、暗黙的変数を評価する方法について説明します。具体的には、DBMS_RULE.EVALUATEプロシージャを使用してイベントが評価されると、イベント・コンテキストは、評価コンテキスト内の暗黙的変数の変数値ファンクションに渡されます。変数値ファンクションの名前はfind_contactであり、このPL/SQLファンクションは、イベント・コンテキストに指定された会社の名前に基づいて担当者を戻します。ルール・セットは、担当者の名前およびイベントの優先度に基づいて評価されます。

この例では、次のルールを使用して顧客の問題を処理します。

- Janeに属するすべての問題は、サンノゼ・センターに割り当てます。

- Fredに属するすべての問題は、ニューヨーク・センターに割り当てます。

- 主担当者が不明のすべての問題は、テキサス・センターのGeorgeに割り当てます。

- 優先度が1の問題については、サポート責任者にアラートが送信されます。

次の手順を実行します。

1. 出力およびスプール結果の表示

2. supportユーザーの作成

3. supportユーザーへのルールに対する必要なシステム権限の付与

4. 顧客の担当者を戻すfind_contactファンクションの作成

5. 評価コンテキストevalctxの作成

6. 問題の優先度および担当者に対応するルールの作成

7. ルール・セットrsの作成

8. ルール・セットへのルールの追加

9. データ・ディクショナリの問合せ

10. PL/SQLプロシージャproblem_dispatchの作成

11. サンプル問題のディスパッチ

12. 環境のクリーンアップ(オプション)

13. スプール結果のチェック

注意:
このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。

/************************* BEGINNING OF SCRIPT ******************************

手順1: 出力およびスプール結果の表示

SET ECHO ONを実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。

*/

SET ECHO ON
SPOOL rules_event_context.out

/*

手順2: supportユーザーの作成

*/

CONNECT SYSTEM

ACCEPT password PROMPT 'Enter password for user: ' HIDE

GRANT ALTER SESSION, CREATE CLUSTER, CREATE DATABASE LINK, CREATE SEQUENCE,
CREATE SESSION, CREATE SYNONYM, CREATE TABLE, CREATE VIEW, CREATE INDEXTYPE,
CREATE OPERATOR, CREATE PROCEDURE, CREATE TRIGGER, CREATE TYPE
TO support IDENTIFIED BY &support;

/*

手順3: supportユーザーへのルールに対する必要なシステム権限の付与

*/

BEGIN
DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE(
privilege    => DBMS_RULE_ADM.CREATE_RULE_SET_OBJ,
grantee      => 'support',
grant_option => FALSE);
DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE(
privilege    => DBMS_RULE_ADM.CREATE_RULE_OBJ,
grantee      => 'support',
grant_option => FALSE);
DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE(
privilege    => DBMS_RULE_ADM.CREATE_EVALUATION_CONTEXT_OBJ,
grantee      => 'support',
grant_option => FALSE);
END;
/

/*

手順4: 顧客の担当者を戻すfind_contactファンクションの作成

*/

CONNECT support

SET FEEDBACK 1
SET NUMWIDTH 10
SET LINESIZE 80
SET TRIMSPOOL ON
SET TAB OFF
SET PAGESIZE 100
SET SERVEROUTPUT ON
CREATE OR REPLACE FUNCTION find_contact(
eco       VARCHAR2,
ecn       VARCHAR2,
var       VARCHAR2,
evctx     SYS.RE$NV_LIST)
RETURN SYS.RE$VARIABLE_VALUE IS
cust      VARCHAR2(30);
contact   VARCHAR2(30);
status    PLS_INTEGER;
BEGIN
IF (var = 'CUSTOMER_CONTACT') THEN
status := evctx.GET_VALUE('CUSTOMER').GETVARCHAR2(cust);
IF (cust = 'COMPANY1') THEN     -- COMPANY1's contact person is Jane
contact := 'JANE';
ELSIF (cust = 'COMPANY2') THEN  -- COMPANY2's contact person is Fred
contact := 'FRED';
ELSE        -- Assign customers without primary contact person to George
contact := 'GEORGE';
END IF;
RETURN SYS.RE$VARIABLE_VALUE('customer_contact',
ANYDATA.CONVERTVARCHAR2(contact));
ELSE
RETURN NULL;
END IF;
END;
/

/*

手順5: 評価コンテキストevalctxの作成

*/

DECLARE
vt  SYS.RE$VARIABLE_TYPE_LIST;
BEGIN
vt := SYS.RE$VARIABLE_TYPE_LIST(
SYS.RE$VARIABLE_TYPE('priority', 'NUMBER', NULL, NULL),
SYS.RE$VARIABLE_TYPE('customer_contact', 'VARCHAR2(30)',
'find_contact', NULL));
DBMS_RULE_ADM.CREATE_EVALUATION_CONTEXT(
evaluation_context_name    => 'evalctx',
variable_types             => vt,
evaluation_context_comment => 'support problem definition');
END;
/

/*

手順6: 問題の優先度および担当者に対応するルールの作成

次のコードを実行すると、それぞれが1つの名前/値ペアを持つアクション・コンテキストが、各ルールに1つずつ作成されます。

*/

DECLARE
ac  SYS.RE$NV_LIST;
BEGIN
ac := SYS.RE$NV_LIST(NULL);
ac.ADD_PAIR('CENTER', ANYDATA.CONVERTVARCHAR2('San Jose'));
DBMS_RULE_ADM.CREATE_RULE(
rule_name       => 'r1',
condition       => ':customer_contact = ''JANE''',
action_context  => ac,
rule_comment    => 'Jane''s customer problems');
ac := sys.re$nv_list(NULL);
ac.ADD_PAIR('CENTER', ANYDATA.CONVERTVARCHAR2('New York'));
DBMS_RULE_ADM.CREATE_RULE(
rule_name       => 'r2',
condition       => ':customer_contact = ''FRED''',
action_context  => ac,
rule_comment    => 'Fred''s customer problems');
ac := sys.re$nv_list(NULL);
ac.ADD_PAIR('CENTER', ANYDATA.CONVERTVARCHAR2('Texas'));
DBMS_RULE_ADM.CREATE_RULE(
rule_name       => 'r3',
condition       => ':customer_contact = ''GEORGE''',
action_context  => ac,
rule_comment    => 'George''s customer problems');
ac := sys.re$nv_list(NULL);
ac.ADD_PAIR('ALERT', ANYDATA.CONVERTVARCHAR2('John Doe'));
DBMS_RULE_ADM.CREATE_RULE(
rule_name       => 'r4',
condition       => ':priority=1',
action_context  => ac,
rule_comment    => 'Urgent problems');
END;
/

/*

手順7: ルール・セットrsの作成

*/

BEGIN
DBMS_RULE_ADM.CREATE_RULE_SET(
rule_set_name      => 'rs',
evaluation_context => 'evalctx',
rule_set_comment   => 'support rules');
END;
/

/*

手順8: ルール・セットへのルールの追加

*/

BEGIN
DBMS_RULE_ADM.ADD_RULE(
rule_name     => 'r1',
rule_set_name => 'rs');
DBMS_RULE_ADM.ADD_RULE(
rule_name     => 'r2',
rule_set_name => 'rs');
DBMS_RULE_ADM.ADD_RULE(
rule_name     => 'r3',
rule_set_name => 'rs');
DBMS_RULE_ADM.ADD_RULE(
rule_name     => 'r4',
rule_set_name => 'rs');
END;
/

/*

手順9: データ・ディクショナリの問合せ

この時点で、前述の手順で作成した評価コンテキスト、ルールおよびルール・セットを表示できます。

*/

COLUMN EVALUATION_CONTEXT_NAME HEADING 'Eval Context Name' FORMAT A30
COLUMN EVALUATION_CONTEXT_COMMENT HEADING 'Eval Context Comment' FORMAT A40

SELECT EVALUATION_CONTEXT_NAME, EVALUATION_CONTEXT_COMMENT
FROM USER_EVALUATION_CONTEXTS
ORDER BY EVALUATION_CONTEXT_NAME;

SET LONGCHUNKSIZE 4000
SET LONG 4000
COLUMN RULE_NAME HEADING 'Rule|Name' FORMAT A5
COLUMN RULE_CONDITION HEADING 'Rule Condition' FORMAT A35
COLUMN ACTION_CONTEXT_NAME HEADING 'Action|Context|Name' FORMAT A10
COLUMN ACTION_CONTEXT_VALUE HEADING 'Action|Context|Value' FORMAT A10

SELECT RULE_NAME,
RULE_CONDITION,
AC.NVN_NAME ACTION_CONTEXT_NAME,
AC.NVN_VALUE.ACCESSVARCHAR2() ACTION_CONTEXT_VALUE
FROM USER_RULES R, TABLE(R.RULE_ACTION_CONTEXT.ACTX_LIST) AC
ORDER BY RULE_NAME;

COLUMN RULE_SET_NAME HEADING 'Rule Set Name' FORMAT A20
COLUMN RULE_SET_EVAL_CONTEXT_OWNER HEADING 'Eval Context|Owner' FORMAT A12
COLUMN RULE_SET_EVAL_CONTEXT_NAME HEADING 'Eval Context Name' FORMAT A25
COLUMN RULE_SET_COMMENT HEADING 'Rule Set|Comment' FORMAT A15

SELECT RULE_SET_NAME,
RULE_SET_EVAL_CONTEXT_OWNER,
RULE_SET_EVAL_CONTEXT_NAME,
RULE_SET_COMMENT
FROM USER_RULE_SETS
ORDER BY RULE_SET_NAME;

/*

手順10: PL/SQLプロシージャproblem_dispatchの作成

*/

CREATE OR REPLACE PROCEDURE problem_dispatch (priority  NUMBER,
customer  VARCHAR2)
IS
vvl       SYS.RE$VARIABLE_VALUE_LIST;
truehits  SYS.RE$RULE_HIT_LIST;
maybehits SYS.RE$RULE_HIT_LIST;
ac        SYS.RE$NV_LIST;
namearray SYS.RE$NAME_ARRAY;
name      VARCHAR2(30);
cval      VARCHAR2(100);
rnum      INTEGER;
i         INTEGER;
status    PLS_INTEGER;
evctx     SYS.RE$NV_LIST;
BEGIN
vvl  := SYS.RE$VARIABLE_VALUE_LIST(
SYS.RE$VARIABLE_VALUE('priority',
ANYDATA.CONVERTNUMBER(priority)));
evctx := SYS.RE$NV_LIST(NULL);
evctx.ADD_PAIR('CUSTOMER', ANYDATA.CONVERTVARCHAR2(customer));
truehits  := SYS.RE$RULE_HIT_LIST();
maybehits := SYS.RE$RULE_HIT_LIST();
DBMS_RULE.EVALUATE(
rule_set_name        => 'support.rs',
evaluation_context   => 'evalctx',
event_context        => evctx,
variable_values      => vvl,
true_rules           => truehits,
maybe_rules          => maybehits);
FOR rnum IN 1..truehits.COUNT LOOP
DBMS_OUTPUT.PUT_LINE('Using rule '|| truehits(rnum).rule_name);
ac := truehits(rnum).rule_action_context;
namearray := ac.GET_ALL_NAMES;
FOR i IN 1..namearray.count LOOP
name := namearray(i);
status := ac.GET_VALUE(name).GETVARCHAR2(cval);
IF (name = 'CENTER') THEN
DBMS_OUTPUT.PUT_LINE('Assigning problem to ' || cval);
ELSIF (name = 'ALERT') THEN
DBMS_OUTPUT.PUT_LINE('Sending alert to: '|| cval);
END IF;
END LOOP;
END LOOP;
END;
/

/*

手順11: サンプル問題のディスパッチ

この手順での最初の問題のディスパッチでは、イベント・コンテキストおよび変数値ファンクションを使用して、COMPANY1の担当者を判別します。イベント・コンテキストはfind_contact変数値ファンクションに渡され、このファンクションによって担当者名JANEが戻されます。したがって、ルールr1がTRUEと評価されます。JANEはサンノゼ・センターに所属するため、problem_dispatchプロシージャによって、問題がサンノゼ・センターに送信されます。また、このイベントの優先度は1であるため、ルールr4がTRUEと評価されます。その結果、problem_dispatchプロシージャによって、サンノゼ・センターにアラートが送信されます。

この手順での2番目の問題のディスパッチでは、イベント・コンテキストおよび変数値ファンクションを使用して、COMPANY2の担当者を判別します。イベント・コンテキストはfind_contact変数値ファンクションに渡され、このファンクションによって担当者名FREDが戻されます。したがって、ルールr2がTRUEと評価されます。FREDはニューヨーク・センターに所属するため、problem_dispatchプロシージャによって、問題がニューヨーク・センターに送信されます。

この手順での3番目の問題のディスパッチでは、イベント・コンテキストおよび変数値ファンクションを使用して、COMPANY3の担当者を判別します。この会社には、専任の担当者はいません。イベント・コンテキストはfind_contact変数値ファンクションに渡され、担当者が見つからなかった場合のデフォルトの担当者がGEORGEであるため、このファンクションによって担当者名GEORGEが戻されます。したがって、ルールr3がTRUEと評価されます。GEORGEはテキサス・センターに属するため、problem_dispatchプロシージャによって、問題がテキサス・センターに送信されます。

*/

EXECUTE problem_dispatch(1, 'COMPANY1');
EXECUTE problem_dispatch(2, 'COMPANY2');
EXECUTE problem_dispatch(5, 'COMPANY3');

/*

手順12: 環境のクリーンアップ(オプション)

supportユーザーを削除して、サンプル環境をクリーンアップできます。

*/

CONNECT SYSTEM

DROP USER support CASCADE;

/*

手順13: スプール結果のチェック

rules_event_context.outスプール・ファイルをチェックして、このスクリプトの完了後にすべてのアクションが正常に終了していることを確認します。

*/

SET ECHO OFF
SPOOL OFF

/*************************** END OF SCRIPT ******************************/

問題のディスパッチおよび表の例の結果のチェック

ここでは、problems表の情報を更新するproblem_dispatchプロシージャを構成します。

- 「表に格納されたデータに対するルールの使用」

- 「明示的変数と表データの両方に対するルールの使用」

- 「暗黙的変数および表データに対するルールの使用」

次の手順に従って、problem_dispatchプロシージャを実行して問題をディスパッチし、problems表内の結果を表示します。

1. データ・ディクショナリの問合せ

2. problems表内の問題の表示

3. problem_dispatchプロシージャの実行による問題のディスパッチ

4. problems表内の問題の表示

5. 環境のクリーンアップ(オプション)

手順1: データ・ディクショナリの問合せ

例で作成した評価コンテキスト、ルールおよびルール・セットを表示します。

CONNECT support
Enter password: password

COLUMN EVALUATION_CONTEXT_NAME HEADING 'Eval Context Name' FORMAT A30
COLUMN EVALUATION_CONTEXT_COMMENT HEADING 'Eval Context Comment' FORMAT A40

SELECT EVALUATION_CONTEXT_NAME, EVALUATION_CONTEXT_COMMENT
FROM USER_EVALUATION_CONTEXTS
ORDER BY EVALUATION_CONTEXT_NAME;

SET LONGCHUNKSIZE 4000
SET LONG 4000
COLUMN RULE_NAME HEADING 'Rule|Name' FORMAT A5
COLUMN RULE_CONDITION HEADING 'Rule Condition' FORMAT A35
COLUMN ACTION_CONTEXT_NAME HEADING 'Action|Context|Name' FORMAT A10
COLUMN ACTION_CONTEXT_VALUE HEADING 'Action|Context|Value' FORMAT A10

SELECT RULE_NAME,
RULE_CONDITION,
AC.NVN_NAME ACTION_CONTEXT_NAME,
AC.NVN_VALUE.ACCESSVARCHAR2() ACTION_CONTEXT_VALUE
FROM USER_RULES R, TABLE(R.RULE_ACTION_CONTEXT.ACTX_LIST) AC
ORDER BY RULE_NAME;

COLUMN RULE_SET_NAME HEADING 'Rule Set Name' FORMAT A20
COLUMN RULE_SET_EVAL_CONTEXT_OWNER HEADING 'Eval Context|Owner' FORMAT A12
COLUMN RULE_SET_EVAL_CONTEXT_NAME HEADING 'Eval Context Name' FORMAT A25
COLUMN RULE_SET_COMMENT HEADING 'Rule Set|Comment' FORMAT A15

SELECT RULE_SET_NAME,
RULE_SET_EVAL_CONTEXT_OWNER,
RULE_SET_EVAL_CONTEXT_NAME,
RULE_SET_COMMENT
FROM USER_RULE_SETS
ORDER BY RULE_SET_NAME;

手順2: problems表内の問題の表示

このSELECT文を実行すると、以前にログに記録された問題が表示されます。

COLUMN probid HEADING 'Problem ID' FORMAT 99999
COLUMN custid HEADING 'Customer ID' FORMAT 99
COLUMN priority HEADING 'Priority' FORMAT 9
COLUMN description HEADING 'Problem Description' FORMAT A30
COLUMN center HEADING 'Center' FORMAT A10

SELECT probid, custid, priority, description, center FROM problems
ORDER BY probid;

出力は次のようになります。

Problem ID Customer ID Priority Problem Description            Center
---------- ----------- -------- ------------------------------ ----------
10301          13        1 no dial tone
10302          23        2 noise on local calls
10303          33        3 noise on long distance calls

挿入されたすべての新しい行のCenter列がNULLであることに注意してください。

手順3: problem_dispatchプロシージャの実行による問題のディスパッチ

problem_dispatchプロシージャを実行します。

SET SERVEROUTPUT ON
EXECUTE problem_dispatch;

手順4: problems表内の問題の表示

手順3で問題が正常にディスパッチされた場合、次のSELECT文を実行すると、各問題がディスパッチされたサポート・センターがCenter列に表示されます。

SELECT probid, custid, priority, description, center FROM problems
ORDER BY probid;

出力は次のようになります。

Problem ID Customer ID Priority Problem Description            Center
---------- ----------- -------- ------------------------------ ----------
10201          12        1 no dial tone                   Tampa
10202          22        2 noise on local calls           New York
10203          32        3 noise on long distance calls   San Jose

注意:
出力は、problem_dispatchプロシージャの作成に使用した例によって異なります。

手順5: 環境のクリーンアップ(オプション)

supportユーザーを削除して、サンプル環境をクリーンアップできます。

CONNECT SYSTEM
Enter password: password

DROP USER support CASCADE;

索引
A  C  D  E  G  I  L  M  N  O  P  Q  R  S  T

A

ALTER TABLEのADD SUPPLEMENTAL LOG DATA句, 3.5

ADD_COLUMNメンバー・プロシージャ, 4.4

ADD_PAIRメンバー・プロシージャ, 6.2, 6.4, 6.5, 6.7

ALTER TABLE文

ADD SUPPLEMENTAL LOG DATA句, 3.5

適用プロセス

DMLハンドラ

作成, 4.4

異機種間環境

例, 2.4.1

取得LCRの再エンキュー, 4.4 ARCHIVELOGモード

取得プロセス, 1.2, 2.2, 4.2

C

取得プロセス

ARCHIVELOGモード, 1.2, 2.2, 4.2

CLOSE_ITERATORプロシージャ, 6.3 COMPATIBLE初期化パラメータ, 1.2, 2.2 競合解消

MAXIMUMハンドラ

例, 3.5

時間ベース

例, 3.5

準備, 3.4

構成

LCR, 5

D

DBMS_RULEパッケージ, 6

DBMS_RULE_ADMパッケージ, 6

DEQUEUEプロシージャ

例, 4.4

DMLハンドラ, 4.4

E

EVALUATEプロシージャ, 6.2, 6.3, 6.4, 6.5, 6.6, 6.7, 6.8

イベント・コンテキスト

例, 6.8

EXECUTEメンバー・プロシージャ, 4.4

G

GET_ALL_NAMESメンバー・ファンクション, 6.2, 6.3, 6.4, 6.5, 6.6, 6.7, 6.8

GET_COMMAND_TYPEメンバー・ファンクション, 4.4

GET_NEXT_HITファンクション, 6.3

GET_OBJECT_NAMEメンバー・ファンクション, 2.4.1

GET_VALUEメンバー・ファンクション

ルール, 6.2, 6.3, 6.4, 6.5, 6.6, 6.7, 6.8

GET_VALUESメンバー・ファンクション, 4.4 GLOBAL_NAMES初期化パラメータ, 1.2, 2.2

I

インスタンス化

例, 2.4.1, 2.4.2, 3.5, 3.5

L

LOB

論理変更レコード, 5

Oracle Streams

構成, 5

論理変更レコード

LOB, 5

論理変更レコード(LCR)

LOB列, 5

M

メッセージ・クライアント

例, 4.4

N

n-wayレプリケーション

例, 3

O

Oracle Streams

データベースの追加, 2.8

オブジェクトの追加, 2.6

初期化パラメータ, 1.2, 2.2

環境の例

LOB, 5

レプリケーション, 1, 2, 3

単一のデータベース, 4

P

伝播

データベース・リンク

作成, 1.3, 2.3, 2.3, 2.8

Q

キュー

ANYDATA

デキュー, 4.4

R

RE$NAME_ARRAYタイプ, 6.5, 6.6, 6.7, 6.8

RE$NV_LISTタイプ, 6.2, 6.4, 6.5, 6.5, 6.6, 6.7, 6.7, 6.8

RE$RULE_HIT_LISTタイプ, 6.2, 6.4, 6.5, 6.6, 6.7, 6.8

RE$TABLE_ALIAS_LISTタイプ, 6.5, 6.6, 6.7, 6.8

RE$TABLE_VALUEタイプ, 6.5, 6.6, 6.7, 6.8

RE$TABLE_VALUE_LISTタイプ, 6.5, 6.6, 6.7, 6.8

RE$VARIABLE_TYPE_LISTタイプ, 6.2, 6.4, 6.6, 6.7, 6.8

RE$VARIABLE_VALUEタイプ, 6.2, 6.3, 6.4, 6.6

RE$VARIABLE_VALUE_LISTタイプ, 6.2, 6.3, 6.4, 6.6

再エンキュー

取得LCR, 4

レプリケーション

データベースの追加, 2.8

オブジェクトの追加, 2.6

単一ソースの異機種間の例, 2

複数ソースの例, 3

n-wayの例, 3

簡単な単一ソースの例, 1

ルール

イベント・コンテキスト

例, 6.8

アプリケーションの例, 6 明示的変数

例, 6.2, 6.6

暗黙的変数

例, 6.7

反復の結果

例, 6.3

MAYBEルール

例, 6.4

部分評価

例, 6.4

表データ

例, 6.5, 6.6, 6.7

S

SET_COMMAND_TYPEメンバー・プロシージャ, 4.4

SET_ENQUEUE_DESTINATIONプロシージャ, 4.4

SET_OBJECT_NAMEメンバー・プロシージャ, 2.4.1, 4.4

SET_RULE_TRANSFORM_FUNCTIONプロシージャ, 2.4.1

SET_VALUESメンバー・プロシージャ, 4.4

サプリメンタル・ロギング

例, 3.5

T

変換

ルールベース

作成, 2.4.1

例, 2.4.1

Oracleの法律上の注意点

コピーライト

Copyright © 1994-2017, Oracle and/or its affiliates. All rights reserved.

ライセンス制約の保証と結果的に生じる損害の免責

このソフトウェアおよび関連ドキュメントの使用と開示は、ライセンス契約の制約条件に従うものとし、知的財産に関する法律により保護されています。ライセンス契約で明示的に許諾されている場合もしくは法律によって認められている場合を除き、形式、手段に関係なく、いかなる部分も使用、複写、複製、翻訳、放送、修正、ライセンス供与、送信、配布、発表、実行、公開または表示することはできません。このソフトウェアのリバース・エンジニアリング、逆アセンブル、逆コンパイルは互換性のために法律によって規定されている場合を除き、禁止されています。

保証免責

ここに記載された情報は予告なしに変更される場合があります。また、誤りが無いことの保証はいたしかねます。誤りを見つけた場合は、オラクルまでご連絡ください。

制限付権利について

このソフトウェアまたは関連ドキュメントを、米国政府機関もしくは米国政府機関に代わってこのソフトウェアまたは関連ドキュメントをライセンスされた者に提供する場合は、次の通知が適用されます。

U.S. GOVERNMENT END USERS: Oracle programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, delivered to U.S. Government end users are "commercial computer software" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such, use, duplication, disclosure, modification, and adaptation of the programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, shall be subject to license terms and license restrictions applicable to the programs. No other rights are granted to the U.S. Government.

危険な用途への使用について

このソフトウェアまたはハードウェアは様々な情報管理アプリケーションでの一般的な使用のために開発されたものです。このソフトウェアまたはハードウェアは、危険が伴うアプリケーション(人的傷害を発生させる可能性があるアプリケーションを含む)への用途を目的として開発されていません。このソフトウェアまたはハードウェアを危険が伴うアプリケーションで使用する際、安全に使用するために、適切な安全装置、バックアップ、冗長性(redundancy)、その他の対策を講じることは使用者の責任となります。このソフトウェアまたはハードウェアを危険が伴うアプリケーションで使用したことに起因して損害が発生しても、Oracle Corporationおよびその関連会社は一切の責任を負いかねます。

商標と登録商標について

OracleおよびJavaはオラクルおよびその関連会社の登録商標です。その他の社名、商品名等は各社の商標または登録商標である場合があります。

Intel、Intel Xeonは、Intel Corporationの商標または登録商標です。すべてのSPARCの商標はライセンスをもとに使用し、SPARC International, Inc.の商標または登録商標です。AMD、Opteron、AMDロゴ、AMD Opteronロゴは、Advanced Micro Devices, Inc.の商標または登録商標です。UNIXは、The Open Groupの登録商標です。

第三者のコンテンツ、製品、サービスに対する免責事項

このソフトウェアまたはハードウェア、そしてドキュメントは、第三者のコンテンツ、製品、サービスへのアクセス、あるいはそれらに関する情報を提供することがあります。適用されるお客様とOracle Corporationとの間の契約に別段の定めがある場合を除いて、Oracle Corporationおよびその関連会社は、第三者のコンテンツ、製品、サービスに関して一切の責任を負わず、いかなる保証もいたしません。適用されるお客様とOracle Corporationとの間の契約に定めがある場合を除いて、Oracle Corporationおよびその関連会社は、第三者のコンテンツ、製品、サービスへのアクセスまたは使用によって損失、費用、あるいは損害が発生しても一切の責任を負いかねます。

Pre-General Availability (一般提供前)版のドキュメントについて

このドキュメントがPre-General Availability (一般提供前)版の場合:

このドキュメントはPre-General Availability (一般提供前)版であり、デモおよび暫定使用のみを目的としたものです。このソフトウェアを使用するハードウェアに限定するものではありません。Oracle Corporationおよびその関連会社は、このドキュメントに関して一切の責任を負わず、いかなる保証もいたしません。また、このドキュメントを使用したことによって損失、費用、あるいは損害が発生しても、一切の責任を負いかねます。

非公開のPre-General Availability (一般提供前)版のドキュメントについて

このドキュメントが非公開のPre-General Availability (一般提供前)版の場合:

このドキュメントに含まれる情報は、情報の共有のみを目的としたものであって、顧客諮問委員会(Customer Advisory Board)のメンバーとしてのお客様の立場でのみ、またはお客様のPre-General Availability Trial Agreement (Pre-GAトライアル契約)のみに従って検討されるべきものとします。マテリアル、コード、または機能の提供をお約束するものではなく、購入決定を行う際の判断材料とすべきではありません。このドキュメントに記載されている特徴または機能の開発、リリースおよび時期については、オラクルの裁量により決定されます。

このドキュメントには、ソフトウェアまたは印刷物などの形式を問わず、オラクルが独占的な権利を有する財産的情報が含まれています。この機密資料へのアクセスと使用は、お客様とオラクルとの間で締結され、お客様が遵守に同意した、Oracle Master Agreement、Oracle License and Oracle Services Agreement (オラクル・ライセンスおよびサービスに関する契約書)、Oracle Partner Network Agreement、Oracle Distribution Agreementまたはその他のライセンス契約の条件に従うものとします。このドキュメントとその内容の開示、コピー、複製および配布には、オラクルによる事前の承諾を必要とします。このドキュメントはライセンス契約の一部となるものではなく、オラクルおよびその子会社や関連会社との契約を構成するものではありません。

ドキュメントのアクセシビリティ

オラクルのアクセシビリティについての詳細情報は、Oracle Accessibility ProgramのWebサイト(http://www.oracle.com/pls/topic/lookup?ctx=acc&id=docacc)を参照してください。

Oracle Supportへのアクセス

サポートをご契約のお客様には、My Oracle Supportを通して電子支援サービスを提供しています。詳細情報は(http://www.oracle.com/pls/topic/lookup?ctx=acc&id=info)か、聴覚に障害のあるお客様は(http://www.oracle.com/pls/topic/lookup?ctx=acc&id=trs)を参照してください。