この章では、Oracleルール・エンジンを使用するルールベースのアプリケーションについて説明します。
この章の例は、Oracle Streamsとは関係ありません。つまり、これらの例では、Oracle Streamsの取得プロセス、伝播、適用プロセスまたはメッセージ・クライアントはルール・エンジンのクライアントではなく、キューも使用されません。
ここでは、ルールベースのアプリケーションの例の構成について説明します。
関連項目: 『Oracle Streams概要および管理』 |
この章の各例では、顧客の問題を処理するルールベースのアプリケーションを作成します。アプリケーションでは、新しい問題がレポートされると、ルールを使用し、問題の優先度に基づいて必要なアクションを決定します。たとえば、アプリケーションでは、それぞれの問題をその優先度に基づいて社内の特定のセンターに割り当てます。
アプリケーションは、これらのルールがルール・エンジンを使用して規定されます。サポートの問題に関連する情報を定義するために、評価コンテキストevalctx
が作成されます。ルールは前述の要件に基づいて作成され、ルール・セットrs
に追加されます。
問題を割り当てるタスクは、ユーザー定義プロシージャproblem_dispatch
によって実行されます。このプロシージャは、ルール・エンジンをコールしてルール・セットrs
内のルールを評価し、TRUE
と評価されるルールに基づいて適切なアクションを実行します。
この例では、ルールを使用して、明示的変数に格納されたデータを評価する方法について説明します。この例では、優先度に基づいて顧客の問題を処理し、次のルールを使用して顧客の問題を処理します。
優先度が2より大きいすべての問題は、サンノゼ・センターに割り当てます。
優先度が2以下のすべての問題は、ニューヨーク・センターに割り当てます。
優先度が1の問題については、サポート責任者にアラートが送信されます。
評価コンテキストには、ディスパッチしている問題の優先度を示す、priority
という1つの明示的変数のみが含まれています。この変数の値は、problem_dispatch
プロシージャによって、DBMS_RULE.EVALUATE
プロシージャに渡されます。
次の手順を実行します。
注意: このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。 |
/************************* BEGINNING OF SCRIPT ******************************
SET
ECHO
ON
を実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。
*/ SET ECHO ON SPOOL rules_stored_variables.out /*
*/
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; /*
*/
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; / /*
*/
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; / /*
次のコードを実行すると、それぞれが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; / /*
*/
BEGIN DBMS_RULE_ADM.CREATE_RULE_SET( rule_set_name => 'rs', evaluation_context => 'evalctx', rule_set_comment => 'support rules'); END; / /*
*/
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; / /*
この時点で、前述の手順で作成した評価コンテキスト、ルールおよびルール・セットを表示できます。
*/ 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; /*
*/
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; / /*
*/
EXECUTE problem_dispatch(1); EXECUTE problem_dispatch(2); EXECUTE problem_dispatch(3); EXECUTE problem_dispatch(5); /*
rules_stored_variables.out
スプール・ファイルをチェックして、このスクリプトの完了後にすべてのアクションが正常に終了していることを確認します。
*/ SET ECHO OFF SPOOL OFF /*************************** END OF SCRIPT ******************************/
この例は、すべての評価結果が一度に戻されるのではなく繰返し戻されることを除き、「明示的変数に格納された表以外のデータに対するルールの使用」の例と同じです。
次の手順を実行します。
注意: このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。 |
/************************* BEGINNING OF SCRIPT ******************************
SET
ECHO
ON
を実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。
*/ SET ECHO ON SPOOL rules_stored_variables_iterative.out /*
「明示的変数に格納された表以外のデータに対するルールの使用」の手順1から8を完了していることを確認します。これらの手順を完了していない場合は、完了してから次の手順に進みます。
*/ PAUSE Press <RETURN> to continue when the preliminary steps have been completed. /*
手順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; / /*
*/
EXECUTE problem_dispatch(1); EXECUTE problem_dispatch(2); EXECUTE problem_dispatch(3); EXECUTE problem_dispatch(5); /*
support
ユーザーを削除して、サンプル環境をクリーンアップできます。
*/ CONNECT SYSTEM DROP USER support CASCADE; /*
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
プロシージャに渡されます。
次の手順を実行します。
注意: このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。 |
/************************* BEGINNING OF SCRIPT ******************************
SET
ECHO
ON
を実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。
*/ SET ECHO ON SPOOL rules_stored_variables_partial.out /*
*/
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; /*
*/
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; / /*
*/
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; / /*
次のコードを実行すると、それぞれが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; / /*
*/
BEGIN DBMS_RULE_ADM.CREATE_RULE_SET( rule_set_name => 'rs', evaluation_context => 'evalctx', rule_set_comment => 'support rules'); END; / /*
*/
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; / /*
この時点で、前述の手順で作成した評価コンテキスト、ルールおよびルール・セットを表示できます。
*/ 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; /*
*/
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; / /*
この手順での最初の問題のディスパッチでは、部分評価を使用し、部分評価に基づいてアクションを実行します。具体的には、最初の問題のディスパッチでは、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'); /*
support
ユーザーを削除して、サンプル環境をクリーンアップできます。
*/ CONNECT SYSTEM DROP USER support CASCADE; /*
rules_stored_variables_partial.out
スプール・ファイルをチェックして、このスクリプトの完了後にすべてのアクションが正常に終了していることを確認します。
*/ SET ECHO OFF SPOOL OFF /*************************** END OF SCRIPT ******************************/
この例では、ルールを使用して、表に格納されたデータを評価する方法について説明します。この例は、「明示的変数に格納された表以外のデータに対するルールの使用」で説明した例に類似しています。いずれの例でも、アプリケーションは優先度に基づいて顧客の問題をルーティングします。ただし、この例では、問題は変数ではなく表に格納されます。
アプリケーションでは、support
スキーマのproblems
表が使用され、この表に顧客の問題が挿入されます。この例では、次のルールを使用して顧客の問題を処理します。
優先度が2より大きいすべての問題は、サンノゼ・センターに割り当てます。
優先度が2以下のすべての問題は、ニューヨーク・センターに割り当てます。
優先度が1の問題については、サポート責任者にアラートが送信されます。
評価コンテキストは、problems
表で構成されています。ルーティングしている問題に対応する、表の関連する行は、表の値としてDBMS_RULE.EVALUATE
プロシージャに渡されます。
次の手順を実行します。
注意: このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。 |
/************************* BEGINNING OF SCRIPT ******************************
SET
ECHO
ON
を実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。
*/ SET ECHO ON SPOOL rules_table.out /*
*/
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; /*
*/
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; / /*
*/
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)); /*
*/
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; / /*
次のコードを実行すると、それぞれが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; / /*
*/
BEGIN DBMS_RULE_ADM.CREATE_RULE_SET( rule_set_name => 'rs', evaluation_context => 'evalctx', rule_set_comment => 'support rules'); END; / /*
*/
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; / /*
*/
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; / /*
*/
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; /*
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
が繰り返しコールされ、ルールの評価が遅くなる場合があります。異なるルールに値が異なる現在の時刻が含まれることによって、不適切な動作が発生する場合があります。
次の手順を実行します。
注意: このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。 |
/************************* BEGINNING OF SCRIPT ******************************
SET
ECHO
ON
を実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。
*/ SET ECHO ON SPOOL rules_var_tab.out /*
*/
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; /*
*/
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; / /*
*/
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)); /*
*/
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; / /*
次のコードを実行すると、それぞれが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; / /*
*/
BEGIN DBMS_RULE_ADM.CREATE_RULE_SET( rule_set_name => 'rs', evaluation_context => 'evalctx', rule_set_comment => 'support rules'); END; / /*
*/
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; / /*
*/
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; / /*
*/
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; /*
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回コールされます。
次のいずれかの条件に該当する場合は、暗黙的変数の使用が他の場合にも役立つ可能性があります。
コール元が変数値に対するアクセス権を持っていない。
変数がルールで頻繁に参照されない。変数は暗黙的であるため、必要な場合にのみその値を取得できます。すべての評価で値を渡す必要はありません。
次の手順を実行します。
注意: このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。 |
/************************* BEGINNING OF SCRIPT ******************************
SET
ECHO
ON
を実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。
*/ SET ECHO ON SPOOL rules_implicit_var.out /*
*/
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; /*
*/
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; / /*
*/
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)); /*
*/
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; / /*
*/
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; / /*
次のコードを実行すると、それぞれが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; / /*
*/
BEGIN DBMS_RULE_ADM.CREATE_RULE_SET( rule_set_name => 'rs', evaluation_context => 'evalctx', rule_set_comment => 'support rules'); END; / /*
*/
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; / /*
*/
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; / /*
*/
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; /*
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の問題については、サポート責任者にアラートが送信されます。
次の手順を実行します。
注意: このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。 |
/************************* BEGINNING OF SCRIPT ******************************
SET
ECHO
ON
を実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。
*/ SET ECHO ON SPOOL rules_event_context.out /*
*/
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; /*
*/
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; / /*
*/
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; / /*
*/
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; / /*
次のコードを実行すると、それぞれが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; / /*
*/
BEGIN DBMS_RULE_ADM.CREATE_RULE_SET( rule_set_name => 'rs', evaluation_context => 'evalctx', rule_set_comment => 'support rules'); END; / /*
*/
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; / /*
この時点で、前述の手順で作成した評価コンテキスト、ルールおよびルール・セットを表示できます。
*/ 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; /*
*/
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; / /*
この手順での最初の問題のディスパッチでは、イベント・コンテキストおよび変数値ファンクションを使用して、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'); /*
support
ユーザーを削除して、サンプル環境をクリーンアップできます。
*/ CONNECT SYSTEM DROP USER support CASCADE; /*
rules_event_context.out
スプール・ファイルをチェックして、このスクリプトの完了後にすべてのアクションが正常に終了していることを確認します。
*/ SET ECHO OFF SPOOL OFF /*************************** END OF SCRIPT ******************************/
ここでは、problems
表の情報を更新するproblem_dispatch
プロシージャを構成します。
次の手順に従って、problem_dispatch
プロシージャを実行して問題をディスパッチし、problems
表内の結果を表示します。
例で作成した評価コンテキスト、ルールおよびルール・セットを表示します。
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;
この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
であることに注意してください。
problem_dispatch
プロシージャを実行します。
SET SERVEROUTPUT ON EXECUTE problem_dispatch;
手順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 プロシージャの作成に使用した例によって異なります。 |
support
ユーザーを削除して、サンプル環境をクリーンアップできます。
CONNECT SYSTEM
Enter password: password
DROP USER support CASCADE;