Oracle execute immediate 拼接條件 引數化
阿新 • • 發佈:2019-01-26
最近在將專案的資料庫改成Oracle,本人對Oracle也是一無所知,邊做邊摸索。
在使用 execute immediate 動態執行SQL分頁,發現網上很多例子都是通過引數值直接拼接成SQL來執行。
對於Oracle新手來說,好像Oracle沒有類似 SQLServer exec sp_executesql 引數化查詢這樣的功能。
例如:
declare p_accountnum varchar2(100); p_groupid integer; p_recordcount integer; p_select varchar2(500); begin p_accountnum := 'gh_xxxxxxxxx'; p_groupid := 109; p_select := 'select count(*) from wxuser where 1=1 and accountnum =''' || p_accountnum || ''' and groupid =' || p_groupid; execute immediate p_select into p_recordcount; dbms_output.put_line(p_recordcount); end;
這樣很明顯的一樣問題,如果引數p_accountnum存在SQL特殊字元,就會出現SQL注入了。當然你也可以在專案程式中對SQL特殊字元進行過濾。
但有時候在寫程式中,可能因各種不小心會忘記對SQL特殊字元過濾,所以最可靠的辦法就是直接將值引數化,不通過引數值直接拼接成SQL來執行。
這是我寫的一個儲存過程,希望可以幫到一些Oracle新手。
procedure SelectByWhere(p_accountnum in varchar2, p_groupid in integer, p_pageindex in integer, p_pagesize in integer, p_recordcount out integer, v_result out pack_wxuser.cur_type) is v_select varchar2(500); v_where varchar2(500); begin v_where := ' where 1=1'; if p_accountnum is not null and length(p_accountnum) > 0 then begin v_where := v_where || ' and accountnum = :a'; end; else begin v_where := v_where || ' and ((1=1) or :a is null)'; end; end if; if p_groupid is not null and p_groupid > 0 then begin v_where := v_where || ' and groupid = :b '; end; else begin v_where := v_where || ' and ((1=1) or :b is null)'; end; end if; v_select := 'select count(*) from wxuser' || v_where; dbms_output.put_line(v_select); execute immediate v_select into p_recordcount using p_accountnum, p_groupid; v_where := v_where || ' order by subscribe_time desc'; if p_pageindex is not null and p_pageindex > 0 and p_pagesize is not null and p_pagesize > 0 then begin v_select := 'select t.* ,g.groupname groupname from (select w.*, rownum as rowno from (select * from wxuser' || v_where || ') w where rownum <=' || (p_pageindex * p_pagesize) || ') t left join wxgroup g on t.groupid=g.groupid where t.rowno >=' || ((p_pageindex - 1) * p_pagesize); end; else begin v_select := 'select t.*,g.groupname groupname from ( select * from wxuser' || v_where || ' ) t left join wxgroup g on t.groupid=g.groupid'; end; end if; dbms_output.put_line(v_select); open v_result for v_select using p_accountnum, p_groupid; end;