sql >> データベース >  >> RDS >> Oracle

動的WHERE句を作成するにはどうすればよいですか?

    目的は、WHERE句の可変数のフィルターからステートメントを動的にアセンブルすることです。再帰がこれらすべてに当てはまる場所がわからないため、配列を使用してパラメーターを処理します。

    SQL> create type qry_param as object
      2      (col_name varchar2(30)
      3      , col_value varchar(20))
      4  /
    
    Type created.
    
    SQL> create type qry_params as table of qry_param
      2  /
    
    Type created.
    
    SQL> 
    

    このテーブルは、配列をループする関数に渡されます。配列のエントリごとに、=''の形式でWHERE句に行を追加します。おそらく、より高度なフィルタリング(さまざまな演算子、明示的なデータ型変換、バインド変数)が必要になりますが、これが一般的な考え方です。

    SQL> create or replace function get_emps
      2      (p_args in qry_params )
      3      return sys_refcursor
      4  as
      5      stmt varchar2(32767);
      6      rc sys_refcursor;
      7  begin
      8      stmt := ' select * from emp';
      9      for i in p_args.first()..p_args.last()
     10      loop
     11          if i = 1 then
     12              stmt := stmt || ' where ';
     13          else
     14              stmt := stmt || ' and ';
     15          end if;
     16          stmt := stmt || p_args(i).col_name
     17                       ||' = '''||p_args(i).col_value||'''';
     18      end loop;
     19      open rc for stmt;
     20      return rc;
     21  end get_emps;
     22  /
    
    Function created.
    
    SQL> 
    

    最後に、このクエリを実行するには、配列型のローカル変数を設定し、結果を参照カーソルに返す必要があります。

    SQL> var l_rc refcursor
    SQL> declare
      2      l_args qry_params := qry_params
      3                             (qry_param('DEPTNO', '50')
      4                                     , qry_param('HIREDATE', '23-MAR-2010'));
      5  begin
      6      :l_rc := get_emps(l_args);
      7  end;
      8  /
    
    PL/SQL procedure successfully completed.
    
    
    SQL> print l_rc
    
         EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM     DEPTNO
    ---------- ---------- --------- ---------- --------- ---------- ---------- ----------
          8041 FEUERSTEIN PLUMBER         7839 23-MAR-10       4250                    50
          8040 VERREYNNE  PLUMBER         7839 23-MAR-10       4500                    50
    
    SQL>    
    

    編集

    質問の最後の段落で、OPは、基準に合格するためにXMLを使用していると述べています。この要件によって、元の実装の形が劇的に変わることはありません。ループは、配列ではなくXPathクエリを実行する必要があります:

    SQL> create or replace function get_emps
      2      (p_args in xmltype )
      3      return sys_refcursor
      4  as
      5      stmt varchar2(32767);
      6      rc sys_refcursor;
      7  begin
      8      stmt := ' select * from emp';
      9      for i in (select * from xmltable (
     10                       '/params/param'
     11                       passing p_args
     12                       columns
     13                           position for ordinality
     14                           , col_name varchar2(30) path '/param/col_name'
     15                           , col_value varchar2(30) path '/param/col_value'
     16                       )
     17               )
     18      loop
     19          if i.position = 1 then
     20            stmt := stmt || ' where ';
     21          else
     22            stmt := stmt || ' and ';
     23          end if;
     24          stmt := stmt || i.col_name
     25                     ||' = '''||i.col_value||'''';
     26      end loop;
     27      open rc for stmt;
     28      return rc;
     29  end get_emps;
     30  /
    
    Function created.
    
    SQL>
    

    ご覧のとおり、このバージョンは以前と同じ結果を返します...

    SQL> var l_rc refcursor
    SQL> declare
      2      l_args xmltype := xmltype
      3                              ('<params>
      4                                  <param>
      5                                      <col_name>DEPTNO</col_name>
      6                                      <col_value>50</col_value>
      7                                  </param>
      8                                  <param>
      9                                      <col_name>HIREDATE</col_name>
     10                                      <col_value>23-MAR-2010</col_value>
     11                                  </param>
     12                              </params>');
     13  begin
     14    :l_rc := get_emps(l_args);
     15  end;
     16  /
    
    PL/SQL procedure successfully completed.
    
    SQL> print l_rc
    
         EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM     DEPTNO
    ---------- ---------- --------- ---------- --------- ---------- ---------- ----------
          8041 FEUERSTEIN PLUMBER         7839 23-MAR-10       4250                    50
          8040 VERREYNNE  PLUMBER         7839 23-MAR-10       4500                    50
    
    SQL>
    


    1. PostgreSQL count(*)が常に遅い場合、複雑なクエリをページ付けする方法は?

    2. ORA-12505を修正する方法、TNS:listenerは現在、接続記述子で指定されたSIDを認識していません

    3. フラットjsonb配列の要素に対するLIKEクエリ

    4. JDBCステートメントの例–バッチ挿入、更新、削除