程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> 關於MYSQL數據庫 >> 詳解動態SQL,如何構造通用動態頁面查詢

詳解動態SQL,如何構造通用動態頁面查詢

編輯:關於MYSQL數據庫

本文節選之《劍破冰山-Oracle開發藝術》一書,喜歡的朋友可以在本站下載。由於動態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;
 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved