動態SQL 構造通用動態頁面查詢

2021-09-04 15:47:24 字數 3209 閱讀 3719

由於動態sql特有的靈活性,我們很容易的按照某種共性去構造通用和重用功能的**,例如基於某個表的動態字段查詢;

但凡事有利有弊;首先動態sql語句無法在編譯前期檢查sql是否正確,必須等到執行期才會發現問題;其次靜態sql是一次解析,多次執行,雖然動態sql也可以使用繫結變數的方式,但是也會帶來一些意想不到的效能問題,例如繫結變數在sql要訪問的表存在資料傾斜時會提供錯誤的執行計畫;最後動態sql語句可讀性較差,比較難以維護。

下面我們就以比較經典的分頁功能為例:

create or replace procedure sp_exec_dynamic_page

( i_tablename   varchar2,    --

表名employees e,departments d

i_tablecolumn varchar2,    --

查詢列a.employee_id,b.department_name

i_where       varchar2,    --

查詢條件b.department_name like 's%'

i_ordercolumn varchar2,    --

排序b.department_name desc

i_pagesize    number,      --

每頁大小20

i_curpage     number,      --

當前頁6

o_rowcount    out number,  --

返回總條數

o_pagecount   out number,  --

返回總頁數

o_cursor      out ref_cursor.t_retdataset --

返回分頁結果集

) is

v_startrecord  int;

v_endrecord    int;

v_pagesize     int;

v_curpage      int;

v_tablecolumn  varchar2(2000);

v_where        varchar2(2000);

v_ordercolumn  varchar2(200);

v_count_sql    varchar2(2000);

v_select_sql   varchar2(2000);

begin

--如果沒有表名稱,則直接返回異常訊息

--如果沒有字段,則表示全部字段

if i_tablecolumn is not null then

v_tablecolumn:=i_tablecolumn;

else

v_tablecolumn:=' * ';

end if;

--可以沒有

where

條件 if i_where is not null then

v_where:=' where 1=1 and '||i_where||' ';

else

v_where:=' where 1=1 ';

end if;

--可以沒有order by條件

if i_ordercolumn is null then

v_ordercolumn:=' ';

else

v_ordercolumn:=' order by '||i_ordercolumn;

end if;

--如果未指定查詢頁,則預設為首頁

if i_curpage is null or i_curpage<1 then

v_curpage:=1;

else

v_curpage:=i_curpage;

end if;

--如果未指定每頁記錄數,則預設為10條記錄

if i_pagesize is null then

v_pagesize:=10;

else

v_pagesize:=i_pagesize;

end if;

--查詢總條數

v_count_sql:='select count(*) from '||i_tablename||v_where;

--構造最核心的查詢語句

v_select_sql:='(select '||v_tablecolumn||' from '||i_tablename||v_where||v_ordercolumn||') e';

--執行查詢,查詢總條數

execute immediate v_count_sql into o_rowcount;

dbms_output.put_line('

查詢總條數sql=>'||v_count_sql);

dbms_output.put_line('

查詢總條數count='||o_rowcount);

--得到總頁數,並進行處理

if mod(o_rowcount,i_pagesize)=0 then

o_pagecount:=o_rowcount/i_pagesize;

else

o_pagecount:=floor(o_rowcount/i_pagesize)+1;

end if;

--如果當前頁大於最大頁數,則取最大頁數

if i_curpage>o_pagecount then

v_curpage:=o_pagecount;

end if;

--設定開始結束的記錄數

v_startrecord := (v_curpage - 1) * v_pagesize + 1;

v_endrecord := v_curpage * v_pagesize;

--進行完整的動態sql語句拼寫

v_select_sql:='select * from '||

'( '||

'   select e.*,rownum rn '||

'     from '||

v_select_sql||

'    where rownum<='||v_endrecord||

') '||

' where rn>='||v_startrecord;

dbms_output.put_line('

查詢sql=>'||v_select_sql);

open o_cursor for v_select_sql;

end;

sql動態查詢

所以我有乙個從網頁傳遞的dict。我想基於dict動態構建查詢。我知道我可以做 session.query myclass filter by web dict 但是,僅當值完全匹配時才起作用。我需要做 像 過濾。我最好的嘗試使用 dict 屬性 for k,v in web dict.items ...

MyBatis動態sql查詢

什麼是動態sql mybatis核心 對sql語句進行靈活操作,通過表示式進行判斷,對sql進行靈活拼接 組裝。需求public class userpo if test userpo.id null and id if if where select id findusercount parame...

SQL動態表查詢

在程式設計過程中,經常會遇到需要根據使用者的選擇進行查詢的情況,這時,使用者不同的選擇可能需要查詢不同的表名,而且這個表名可能還不宜事先在程式中定死,需要能動態的隨機選擇。當然還包括表名和使用者的某些資訊相關,可能不同的使用者需要進入不同的表,甚至表名的一部分就是使用者名稱的一部分,等等。對於這些情...