ヘッダーをスキップ
Oracle® Streams拡張例
11gリリース2 (11.2)
B61356-02
  目次へ移動
目次
索引へ移動
索引

前
 
次
 

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: サンプル問題のディスパッチ

この手順での最初の問題のディスパッチでは、部分評価を使用し、部分評価に基づいてアクションを実行します。具体的には、最初の問題のディスパッチでは、priority1problem_typeNULLに指定します。この場合、ルール・エンジンによってイベントの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が戻されます。したがって、ルールr1TRUEと評価されます。JANEはサンノゼ・センターに所属するため、problem_dispatchプロシージャによって、問題がサンノゼ・センターに送信されます。また、このイベントの優先度は1であるため、ルールr4TRUEと評価されます。その結果、problem_dispatchプロシージャによって、サンノゼ・センターにアラートが送信されます。

この手順での2番目の問題のディスパッチでは、イベント・コンテキストおよび変数値ファンクションを使用して、COMPANY2の担当者を判別します。イベント・コンテキストはfind_contact変数値ファンクションに渡され、このファンクションによって担当者名FREDが戻されます。したがって、ルールr2TRUEと評価されます。FREDはニューヨーク・センターに所属するため、problem_dispatchプロシージャによって、問題がニューヨーク・センターに送信されます。

この手順での3番目の問題のディスパッチでは、イベント・コンテキストおよび変数値ファンクションを使用して、COMPANY3の担当者を判別します。この会社には、専任の担当者はいません。イベント・コンテキストはfind_contact変数値ファンクションに渡され、担当者が見つからなかった場合のデフォルトの担当者がGEORGEであるため、このファンクションによって担当者名GEORGEが戻されます。したがって、ルールr3TRUEと評価されます。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;