確かに興味深い質問です。これには2つの側面があります。
1つ目は、それが良いアイデアかどうかです。問題は、ルール内のテキストがデータベースから見えないことです。依存関係チェックには表示されないため、影響分析は困難になります。明らかに(または明らかにではないかもしれませんが)、ルールの構文はそれを実行することによってのみ検証できます。これにより、ルールの追加で問題が発生する可能性があります。したがって、メンテナンスの問題になることもあります。そして、これから見ていくように、単純なクエリを超えてプログラムするのは困難です。
2番目の側面はそれが可能かどうかです。です。動的SQLを使用する必要があります。動的SQLと静的SQLを組み合わせるのは実行可能ですが、厄介です。
create table rules (project_name varchar2(30)
, rule_name varchar2(30)
, rule_text varchar2(4000) )
/
insert into rules
values ('SO', 'ACC_SALES'
, 'select ACCOUNTNUMBER from CUSTOMERS where ACCUMULATED_SALES > 500000 ')
/
create table customers (accountnumber number(7,0)
, name varchar2(20)
, accumulated_sales number
, sales_region varchar2(3))
/
insert into customers values (111, 'ACME Industries', 450000, 'AA')
/
insert into customers values (222, 'Tyrell Corporation', 550000, 'BB')
/
insert into customers values (333, 'Lorax Textiles Co', 500000, 'BB')
/
この関数はルールを取得して実行し、数値配列を返します。
create or replace type rule_numbers as table of number
/
create or replace function exec_numeric_rule
( p_pname in rules.project_name%type
, p_rname in rules.rule_name%type )
return rule_numbers
is
return_value rule_numbers;
stmt rules.rule_text%type;
begin
select rule_text into stmt
from rules
where project_name = p_pname
and rule_name = p_rname;
execute immediate stmt
bulk collect into return_value;
return return_value;
end exec_numeric_rule;
/
テストしてみましょう。
SQL> select * from customers
2 where accountnumber in
3 ( select * from table (exec_numeric_rule('SO', 'ACC_SALES')))
4 /
ACCOUNTNUMBER NAME ACCUMULATED_SALES SAL
------------- -------------------- ----------------- ---
222 Tyrell Corporation 550000 BB
1 row selected.
SQL>
これが唯一の正解です。
しかし今、私たちはあなたの補足的な質問に行き着きます:
「保存されたクエリが独自の変数を使用する場合、それは可能ですか?」
はい、できますが、物事はもう少しもろくなり始めます。新しいルール:
insert into rules
values ('SO', 'ACC_SALES_VAR'
, 'select ACCOUNTNUMBER from CUSTOMERS where ACCUMULATED_SALES > :LMT ')
/
関数を修正して適用します。
create or replace function exec_numeric_rule
( p_pname in rules.project_name%type
, p_rname in rules.rule_name%type
, p_variable in number := null)
return rule_numbers
is
return_value rule_numbers;
stmt rules.rule_text%type;
begin
select rule_text into stmt
from rules
where project_name = p_pname
and rule_name = p_rname;
if p_variable is null then
execute immediate stmt
bulk collect into return_value;
else
execute immediate stmt
bulk collect into return_value
using p_variable;
end if;
return return_value;
end exec_numeric_rule;
/
成功を祈っている!
SQL> select * from customers
2 where accountnumber in
3 ( select * from table (exec_numeric_rule('SO', 'ACC_SALES_VAR', 480000)))
4 /
ACCOUNTNUMBER NAME ACCUMULATED_SALES SAL
------------- -------------------- ----------------- ---
222 Tyrell Corporation 550000 BB
333 Lorax Textiles Co 500000 BB
2 rows selected.
SQL>
さて、それでも動作します。しかし、順列は友好的ではないことがわかります。RULEに複数の引数を渡したい場合は、より多くの関数またはよりねじれた内部ロジックが必要です。日付または文字列のセットを返したい場合は、より多くの関数が必要です。異なるdata_typesのP_VARIABLEパラメータを渡したい場合は、より多くの関数が必要になる場合があります。確かに、いくつかの型チェックの前提条件が必要です。
これは私の最初のポイントに戻ります:はい、それは可能ですが、それは面倒な価値がありますか?