动态sql中动态绑定变量数 - Open Cursor

时间:2017-09-18 10:02:07

标签: sql oracle plsql

在我的存储过程中,我有一个动态查询 - where子句中的条件数因输入参数而异。

    in params - x, y, z

    searchsql := 'select select1, select2, select3 from tableA where 1 = 1 and ';

    if(x is not null) then
       searchSql := searchSql || PKG_COMMON.GET_SQL_BINDTXTFLD(x,'select1','a');
       -- above package will return  AND upper(select1) like upper(:a)
       cursorParams := cursorParams || ':' || x || ',';
    end if;

    if(y is not null) then
       searchSql := searchSql || PKG_COMMON.GET_SQL_BINDTXTFLD(y,'select2','b');
       -- above package will return  AND upper(select2) like upper(:b)
       cursorParams := cursorParams || ':' || y || ',';
    end if;

--I am trimming the last comma of the cursor param

     SELECT SUBSTR(cursorParams, 1, INSTR(cursorParams , ',', -1)-1)
            INTO cursorParams FROM dual;

    open resultCursor for searchSql using cursorParams

现在,我有上面的游标需要使用传递的params打开,但是在这种情况下,params的数量取决于sql是如何形成的。所以我使用cursorParams变量动态形成绑定变量

但是这些值没有绑定,只能设置为第一个参数

如何正确绑定,我已经尝试过执行立即选项

3 个答案:

答案 0 :(得分:1)

出了什么问题:

select select1, select2, select3 
from tableA 
where (:a is null
  OR upper(select1) like upper(:a))
and (:b is null
  OR upper(select2) like upper(:b))
and (:c is null
  OR upper(select3) like upper(:c));

(假设您已禁用绑定查看)

答案 1 :(得分:0)

http://docs.oracle.com/cloud/latest/db121/ARPLS/d_sql.htm

Native Dynamic SQL是DBMS_SQL的替代方法,它允许您将动态SQL语句直接放入PL / SQL块中。在大多数情况下,Native Dynamic SQL比DBMS_SQL更易于使用和执行。但是,Native Dynamic SQL本身有一些限制:

不支持所谓的方法4(对于输入或输出数量未知的动态SQL语句)

答案 2 :(得分:0)

以下是使用DBMS_SQL动态构建和绑定的一个简单示例。

DECLARE
  i_owner       all_objects.owner%TYPE := 'SYS';
  i_object_name all_objects.object_name%TYPE := 'DUAL';
  i_object_type all_objects.object_type%TYPE := NULL;

  v_statement VARCHAR2(4000);
  v_cursor    BINARY_INTEGER := dbms_sql.open_cursor;
  v_rows      BINARY_INTEGER;
  v_result    SYS_REFCURSOR;

  v_owner       all_objects.owner%TYPE;
  v_object_name all_objects.object_name%TYPE;
  v_object_type all_objects.object_type%TYPE;
BEGIN
  v_statement := 'select owner, object_name, object_type from all_objects where 1 = 1';

  IF i_owner IS NOT NULL THEN
    v_statement := v_statement ||
                   q'[ and owner like upper(:owner) || '%']';
  END IF;

  IF i_object_name IS NOT NULL THEN
    v_statement := v_statement ||
                   q'[ and object_name like upper(:object_name) || '%']';
  END IF;

  IF i_object_type IS NOT NULL THEN
    v_statement := v_statement ||
                   q'[ and object_type like upper(:object_type) || '%']';
  END IF;

  dbms_output.put_line(v_statement);

  dbms_sql.parse(c             => v_cursor,
                 STATEMENT     => v_statement,
                 language_flag => dbms_sql.native);

  IF i_owner IS NOT NULL THEN
    dbms_sql.bind_variable(c     => v_cursor,
                           NAME  => 'owner',
                           VALUE => i_owner);
  END IF;

  IF i_object_name IS NOT NULL THEN
    dbms_sql.bind_variable(c     => v_cursor,
                           NAME  => 'object_name',
                           VALUE => i_object_name);
  END IF;

  IF i_object_type IS NOT NULL THEN
    dbms_sql.bind_variable(c     => v_cursor,
                           NAME  => 'object_type',
                           VALUE => i_object_type);
  END IF;

  v_rows := dbms_sql.execute(c => v_cursor);

  IF v_rows >= 0 THEN
    v_result := dbms_sql.to_refcursor(cursor_number => v_cursor);

    LOOP
      FETCH v_result
        INTO v_owner,
             v_object_name,
             v_object_type;
      EXIT WHEN v_result%NOTFOUND;

      dbms_output.put_line(v_owner || ' ' || v_object_name || ' ' ||
                           v_object_type);
    END LOOP;
  END IF;
END;
/