5

Oracleデータベースには、SQLQUERYというフィールドを持つRULESというテーブルがあります。このフィールドは、SQLステートメントが格納されているvarcharです。PKはDM_PROJECTです。

保存される典型的なステートメントは次のようになります。

select ACCOUNTNUMBER from CUSTOMERS where ACCUMULATED_SALES > 500000

私はこのようなことをしたい:

select 
  * 
from 
  customers 
where
     accountnumber like 'A%'
  or salesregion = 999
  or accountnumber in
     (
       <run the query SQLQUERY from RULES where DM_PROJECT=:DM_PROJECT>
     )

これはできますか?

(二次的な懸念:保存されたクエリが次のような独自の変数を使用する場合に実行できますか?

select ACCOUNTNUMBER from CUSTOMERS where ACCUMULATEDSALES > :LIMIT 

)。

4

2 に答える 2

10

確かに興味深い質問です。これには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パラメータを渡したい場合は、より多くの関数が必要になる場合があります。確かに、いくつかの型チェックの前提条件が必要です。

これは私の最初のポイントに戻ります:はい、それは可能ですが、それは面倒な価値がありますか?

于 2010-08-12T11:09:31.170 に答える
0

動的SQL(即時実行)を使用できます。詳細については、即時実行を参照してください。

于 2010-08-12T09:38:12.363 に答える