/*
TABLE_NAME_IN 表名(只支持单表,多表时请用视图封装)
SQL_WHERE_IN 条件语句 例如 : where n_xh < 200
SQL_ORDERBY_IN 排序语句 例如 : order by n_xh desc
IDX_PAGE_IN 请求的页数
CURR_PAGE_COUNT_IN 每页的行数
PAGE_NOW_N_OUT 当前的页数
PAGE_SUM_N_OUT 总页数
PAGE_DATA_EVERYCOUNT_N_OUT 每页个数
PAGE_DATA_SUM_COUNT_N_OUT 总页数
return 结果集动态游标 包含表或者视图中的所有字段+行序号,如果没有表或者视图,或者where语句、orderby语句书写错误
那么返回下列信息
DQYS ZYS MYGS ZGS
---------- ---------- ---------- ----------
0 0 0 0
行序号 PROW
曾经使用java做过一个完全隔离中间件层的小程序
使用java map存放结果集的元数据(列名)以及对应的列值,
map的个数=表或者视图中column的个数
每个map中键值对的个数=表或者视图中的行数
然后封装为json格式的String最后返回给客户端
这样每次只需要修改视图的定义信息以及前台页面的jquery 代码即可,中间件层面的代码完全不需要修改
感兴趣的可以试一下。
大数据量分页的话,可以考虑不显示具体的总页数,和总个数。具体可以参考一下google或者百度
*/
CREATE OR REPLACE FUNCTION CURRENT_PAGE(TABLE_NAME_IN IN VARCHAR2,
SQL_WHERE_IN IN VARCHAR2,
SQL_ORDERBY_IN IN VARCHAR2,
IDX_PAGE_IN IN NUMBER,
CURR_PAGE_COUNT_IN IN NUMBER,
PAGE_NOW_N_OUT OUT NUMBER ,
PAGE_SUM_N_OUT OUT NUMBER ,
PAGE_DATA_EVERYCOUNT_N_OUT OUT NUMBER ,
PAGE_DATA_SUM_COUNT_N_OUT OUT NUMBER
) RETURN SYS_REFCURSOR
IS
CURR_ORDERBY_V VARCHAR2 (2000) ; --动态SQL的orderby条件语句
CURR_SQL_V VARCHAR2 (20000) ; --分页语句动态SQL
CURR_COUNT_SQL_V VARCHAR2 (20000) ; --封装了查询数量SQL
CURR_NONEDATA_SQL_V VARCHAR2 (2000) := 'SELECT 0 AS DQYS , 0 AS ZYS , 0 AS MYGS , 0 AS ZGS FROM DUAL '; --没有数据时返回结果集的SQL
MIN_IDX_N NUMBER ; --最小开始序号
RS_REFCUR SYS_REFCURSOR ; --结果集返回游标
BEGIN
CURR_COUNT_SQL_V := 'SELECT COUNT(*) AS GS FROM '||TABLE_NAME_IN||' TT '||SQL_WHERE_IN ;
BEGIN
EXECUTE IMMEDIATE CURR_COUNT_SQL_V INTO PAGE_DATA_SUM_COUNT_N_OUT ; --得到总个数
EXCEPTION --表或视图不存在错误截获
WHEN OTHERS THEN
PAGE_DATA_SUM_COUNT_N_OUT := 0 ;
END ;
--如果总个数为0,那么输出为四列信息
IF PAGE_DATA_SUM_COUNT_N_OUT = 0 THEN
CURR_SQL_V := CURR_NONEDATA_SQL_V ;
PAGE_NOW_N_OUT := 0 ;
PAGE_SUM_N_OUT := 0 ;
PAGE_DATA_EVERYCOUNT_N_OUT := 0 ;
ELSE
IF SQL_ORDERBY_IN IS NOT NULL THEN
CURR_ORDERBY_V := SQL_ORDERBY_IN || ', ROWID DESC ' ; --ORDER BY 后面加上rowid排序,防止分页语句bug
END IF ;
IF CURR_PAGE_COUNT_IN IS NULL OR CURR_PAGE_COUNT_IN = 0 THEN
PAGE_DATA_EVERYCOUNT_N_OUT := 20 ; --默认为每页20条
ELSE
PAGE_DATA_EVERYCOUNT_N_OUT := TRUNC(CURR_PAGE_COUNT_IN) ;
END IF ;
PAGE_SUM_N_OUT := FLOOR (PAGE_DATA_SUM_COUNT_N_OUT/PAGE_DATA_EVERYCOUNT_N_OUT) ; --小数点截掉
IF PAGE_DATA_SUM_COUNT_N_OUT MOD PAGE_DATA_EVERYCOUNT_N_OUT <> 0 THEN --判断总数和页面个数是否可以整除,如果不可以整除则总页数加1
PAGE_SUM_N_OUT := PAGE_SUM_N_OUT +1 ;
END IF ;
IF IDX_PAGE_IN IS NULL OR IDX_PAGE_IN = 0 THEN
PAGE_NOW_N_OUT := 1 ; --如果当前页码为0或者为空,那么默认为1
ELSE
PAGE_NOW_N_OUT := IDX_PAGE_IN ;
END IF ;
IF PAGE_NOW_N_OUT > PAGE_SUM_N_OUT THEN --如果当前页数大于总页数 那么使当前页数等于总页数 也就是最后一页
PAGE_NOW_N_OUT := PAGE_SUM_N_OUT ;
END IF ;
MIN_IDX_N := (PAGE_NOW_N_OUT - 1)*PAGE_DATA_EVERYCOUNT_N_OUT ; --结果集最小开始rownum
--封装语句
/* example :
select * from (select rownum rownum_, TTT.* from ((SELECT TT.*
FROM TEST TT order by name desc
)TTT) where rownum <= :1) where rownum_ > :2
*/
CURR_SQL_V := 'select * '||
' from (select rownum rownum_, TTT.* '||
' from ((SELECT TT.*
FROM '||TABLE_NAME_IN||' TT '
||SQL_WHERE_IN||' '||CURR_ORDERBY_V||'
)TTT) ' ||
' where rownum <= :1) '||
' where rownum_ > :2' ;
END IF ;
OPEN RS_REFCUR FOR CURR_SQL_V USING MIN_IDX_N+PAGE_DATA_EVERYCOUNT_N_OUT , MIN_IDX_N ; --打开动态游标
RETURN RS_REFCUR ; --返回
END CURRENT_PAGE;
create table test as select level as id , 'name'||level as name from dual connect by level <= 10000
/
将如下内容加入到test.sql文件中
var result refcursor
var table_name_in varchar2(4000)
var sql_where_in varchar2(4000)
var sql_orderby_in varchar2(4000)
var idx_page_in number
var curr_page_count_in number
var page_now_n_out number
var page_sum_n_out number
var page_data_everycount_n_out number
var page_data_sum_count_n_out number
exec :table_name_in := '&table_name' ;
exec :sql_where_in := '&sql_where';
exec :sql_orderby_in := '&sql_order';
exec :idx_page_in := to_number('&curr_page');
exec :curr_page_count_in := to_number('&page_count') ;
begin
:result := current_page(table_name_in => :table_name_in,
sql_where_in => :sql_where_in,
sql_orderby_in => :sql_orderby_in,
idx_page_in => :idx_page_in,
curr_page_count_in => :curr_page_count_in,
page_now_n_out => :page_now_n_out,
page_sum_n_out => :page_sum_n_out,
page_data_everycount_n_out => :page_data_everycount_n_out,
page_data_sum_count_n_out => :page_data_sum_count_n_out);
end;
/
print result ;
print page_now_n_out ;
print page_sum_n_out ;
print page_data_everycount_n_out ;
print page_data_sum_count_n_out ;
_dexter@DAVID> @test
Enter value for table_name: TEST
PL/SQL procedure successfully completed.
Enter value for sql_where: where id >= 1000
PL/SQL procedure successfully completed.
Enter value for sql_order: order by name desc
PL/SQL procedure successfully completed.
Enter value for curr_page: 10
PL/SQL procedure successfully completed.
Enter value for page_count: 10
PL/SQL procedure successfully completed.
PL/SQL procedure successfully completed.
PROW ID NAME
---------- ---------- --------------------------------------------
91 9909 name9909
92 9908 name9908
93 9907 name9907
94 9906 name9906
95 9905 name9905
96 9904 name9904
97 9903 name9903
98 9902 name9902
99 9901 name9901
100 9900 name9900
10 rows selected.
PAGE_NOW_N_OUT
--------------
10
PAGE_SUM_N_OUT
--------------
901
PAGE_DATA_EVERYCOUNT_N_OUT
--------------------------
10
PAGE_DATA_SUM_COUNT_N_OUT
-------------------------
9001
结束