2011-02-08 71 views
1

我有一個有多個參數的PL/SQL過程。當一個Web應用程序調用的程序,如果它不使用特定的參數,它傳遞的是空,即動態PL/SQL查詢,如何忽略空參數?

procedure test (param1 in varchar2, param2 in varchar2, param3 in varchar2, cursor out sys_refcursor) 
... 
end procedure test; 

我想打一個SQL查詢,其中包括我在給定的參數WHERE子句僅在參數不爲null。有沒有辦法在一個優雅的方式來實現這一目標,比建設中的SQL查詢字符串,然後打開遊標爲字符串,這樣

vSQL := 'SELECT * from TABLE WHERE something = something_else'; 
if param1 IS NOT NULL 
    vSQL := vSQL || 'AND some_param = ' || param1; 
+0

我想指出的是,如果參數被不斷暴露給用戶,這是一個具有代碼一個典型的例子SQL *注入的高風險。所以你應該使用DBMS_ASSERT來檢查你的最終SQL是否有良好的行爲。 – 2011-02-08 17:24:07

+0

[類似問題](http://stackoverflow.com/questions/317377/sql-if-statement-in-where-clause-for-searching-database#317386) – 2011-02-08 11:10:49

回答

1

你可以把它的所有代碼到一個單一的選擇

SELECT * from TABLE WHERE something = something_else 
AND ((param1 IS NOT NULL AND some_param = param1) OR 1) 
0

創建一個測試表:

create table testtab 
(
name_first varchar2(50), 
name_last varchar2(50), 
name_middle varchar2(50) 
); 

insert into testtab values ('Joe', 'Jones', 'A'); 
insert into testtab values ('Joe', 'Smith', 'A'); 
insert into testtab values ('Steve', 'Jones', 'B'); 
insert into testtab values ('Axl', 'Rose', 'C'); 
insert into testtab values ('Phil', 'McCracken', 'D'); 
commit; 

創建過程:

CREATE OR REPLACE procedure ECDATA.get_testtab_rows 
(i_name_first in varchar2 default null, 
i_name_last in varchar2 default null, 
i_name_middle in varchar2 default null, 
o_cursor out sys_refcursor 
) as 

    v_result_cur sys_refcursor; 

begin 

    open v_result_cur for 
     select * from testtab 
     where name_first like nvl(i_name_first, '%') 
     and name_last like nvl(i_name_last, '%') 
     and name_middle like nvl(i_name_middle, '%') 
    ; 

    o_cursor := v_result_cur; 

end; 
/

然後調用它像這樣:

declare 

    v_cur sys_refcursor; 
    testtab_rec testtab%rowtype; 

begin 

    get_testtab_rows(i_name_last=>'Jones', o_cursor=>v_cur); 
    loop 

     fetch v_cur into testtab_rec; 
     exit when v_cur%notfound; 
     dbms_output.put_line(testtab_rec.name_first || ' ' || testtab_rec.name_middle || ' ' || testtab_rec.name_last); 

    end loop; 

exception 
    when others then raise; 
end;