2017-09-18 30 views
0

在我的存儲過程中,我有一個動態查詢 - where子句中的條件數量因輸入參數而異。動態sql中綁定變量的動態數量 - 打開遊標

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變量

動態形成的綁定變量,但數值並不具有約束力,但只設置到第一個參數

如何正確綁定,我已經嘗試過執行即時選項

+0

我認爲這是一個類似的問題,下面的一個。 https://stackoverflow.com/questions/2514254/how-can-i-create-a-dynamic-where-clause – Jignesh

+0

@Jignesh,這是動態查詢,而不是動態綁定變量與動態查詢 –

+0

@SrikanthA這可能是一個https://stackoverflow.com/q/7816402/409172的副本我對這個問題的回答可能適用於此處。 –

回答

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)); 

(假設你已經綁定偷看禁用)

0

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

原生動態SQL是DBMS_SQL的替代品,它允許您將動態SQL語句直接放置到PL/SQL塊中。在大多數情況下,Native Dynamic SQL比DBMS_SQL更易於使用和執行。然而,本地動態SQL本身具有一定的侷限性:

有所謂的方法4(對於有數目不詳的輸入或輸出動態SQL語句)

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; 
/