如何创建"动态"WHERE子句?

The*_*nge 5 oracle select plsql

第一:谢谢!

我完成了我的另一个项目和惊喜:现在一切正常:-)感谢一些有用的SO思想家!

所以我在这里继续下一个项目.

我想得到这样的东西:

SELECT * FROM tablename WHERE field1=content AND field2=content2 ...
Run Code Online (Sandbox Code Playgroud)

正如您所注意到的那样,这可能是一个非常长的where子句.tablename是一个不会改变的静态属性. field1,, field2...(!),内容可以改变.

所以我需要一个选项来在递归函数中在PL/SQL中构建一个SQL语句.我真的不知道要搜索什么,所以我在这里要求链接甚至一个词来搜索..

请不要开始争论是否真的需要递归函数或它的不足之处 - 这不是问题;-)

如果你可以帮我创建像SQL-String这样以后能够成功完成SELECT的东西,这将是非常好的!

我能够通过递归函数并每次创建一个更长的字符串,但我不能从它做一个SQL语句..

哦,还有一件事:我通过xmlType(xmldom.domdocument等)获取字段和内容我可以从xmltype获取字段和内容,例如clob

APC*_*APC 6

目标是从 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> 
Run Code Online (Sandbox Code Playgroud)

该表被传递给一个函数,该函数循环数组。对于数组中的每个条目,它都会以 <name> = '<value>' 格式将一行附加到 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> 
Run Code Online (Sandbox Code Playgroud)

最后,为了执行此查询,我们需要填充数组类型的局部变量并将结果返回到引用游标。

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>    
Run Code Online (Sandbox Code Playgroud)

编辑

在问题的最后一段中,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>
Run Code Online (Sandbox Code Playgroud)

可以看到,这个版本返回的结果与以前相同......

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>
Run Code Online (Sandbox Code Playgroud)


Ren*_*ene 0

在 PLSQL 中你可以这样做:

declare
  l_statement varchar2(32767);
begin
  l_statement := 'SELECT * FROM tablename WHERE field1=:a AND field2=:b';

  -- you now have you query. Put in the values that you like.
  execute immediate l_statement
  using 'value1','value2';
end;
Run Code Online (Sandbox Code Playgroud)