--创建一个共用的返回结果集的包体 add by xsun 2015-12-05
create or replace package PKG_RefCursor
is
type cur_query is ref cursor;
end PKG_RefCursor;
/*
strWhere:查询条件
currentindex:当前页码
pagesize:每页显示的记录数
totalrows:总记录数
dt:返回的结果集
add by xsun 2015-12-05
*/
create or replace procedure Get_PageClick_Query(strWhere varchar2,currentindex number,pagesize number,totalrows out number,dt out PKG_RefCursor.cur_query)
is
cur_size number:=0;--当前开始记录数
cur_row number:=0;--最后显示记录数
min_rn number; --取出每次查询出的最小记录开始的数字
v_sql varchar2(4000):='';
begin
cur_size:=(currentindex-1)*pagesize;
cur_row:=pagesize*currentindex;
v_sql:='
select count(1),min(t.rn) from
(select substr(sys_connect_by_path (s.module_name, ''/''),2,instr(sys_connect_by_path (s.module_name, ''/''),''/'',1,2)-2) as MenuName1,
substr(sys_connect_by_path (s.module_name, ''/''),instr(sys_connect_by_path (s.module_name, ''/''),''/'',1,2)+1,instr(sys_connect_by_path (s.module_name, ''/''),''/'',-1,1)-instr(sys_connect_by_path (s.module_name, ''/''),''/'',1,2)-1) as MenuName2,
substr(sys_connect_by_path (s.module_name, ''/''),instr(sys_connect_by_path (s.module_name, ''/''),''/'',-1,1)+1) as MenuName3,
--sys_connect_by_path (s.module_name, ''/''),
s.path as pathurl,
rownum rn,
s.state as MenuState from sys_modules s
where connect_by_isleaf=1
start with s.parent_module_id is null connect by s.parent_module_id= prior s.id) t where ' || strWhere;
EXECUTE IMMEDIATE v_sql INTO totalrows,min_rn; --EXECUTE IMMEDIATE 执行动态SQL语句时,单引号只能用''来代替不能用chr(39),否则出错
---为什么要每次取查询的最小记录数,因为它在t子查询里已经标识好RN的顺序,如果按网上说的那写法,当页数递增时,效率越来越低。(只有在排序连续情况下可行)
--cur_size:=min_rn+cur_size;--重新计算开始记录数
--cur_row:=min_rn+cur_row; --重新计算结束开始记录数
v_sql:='select tmp.MenuName1,tmp.MenuName2,tmp.MenuName3,tmp.MenuState,tmp.MenuZTJ,tmp.MenuDayTj from
(select t.MenuName1,t.MenuName2,t.MenuName3,t.MenuState,rownum rx,
(select count(1) from qms_pages_click q
start with q.visited_url_sub=t.pathurl connect by q.parentid= prior q.id) MenuZTJ,
(select count(1) from qms_pages_click q
start with q.visited_url_sub=t.pathurl and to_char(q.visited_date,''yyyy-MM-dd'')=to_char(sysdate,''yyyy-MM-dd'')
connect by q.parentid= prior q.id) MenuDayTj from
(select substr(sys_connect_by_path (s.module_name, ''/''),2,instr(sys_connect_by_path (s.module_name, ''/''),''/'',1,2)-2) as MenuName1,
substr(sys_connect_by_path (s.module_name, ''/''),instr(sys_connect_by_path (s.module_name, ''/''),''/'',1,2)+1,instr(sys_connect_by_path (s.module_name, ''/''),''/'',-1,1)-instr(sys_connect_by_path (s.module_name, ''/''),''/'',1,2)-1) as MenuName2,
substr(sys_connect_by_path (s.module_name, ''/''),instr(sys_connect_by_path (s.module_name, ''/''),''/'',-1,1)+1) as MenuName3,
--sys_connect_by_path (s.module_name, ''/''),
s.path as pathurl,
rownum rn,
s.state as MenuState from sys_modules s
where connect_by_isleaf=1
start with s.parent_module_id is null connect by s.parent_module_id= prior s.id) t where ' || strWhere || 'and rownum<=' || cur_row || ' ) tmp' || ' where rx>'|| cur_size;
dbms_output.put_line(v_sql);
open dt for v_sql; ---返回结果集时,动态语句单引号只能用''来代替不能用chr(39),否则出错
end;
--调用方法 add by xsun 2015-12-05
declare
totalcount number;
ref_cursor sys_refcursor;
m1 varchar2(200);
m2 varchar2(200);
m3 varchar2(200);
m_sate varchar2(20);
zj number;
dj number;
begin
Get_PageClick_Query('t.MenuName1=''系统管理''',1,20,totalcount,ref_cursor);
loop
fetch ref_cursor into m1,m2,m3,m_sate,zj,dj;
exit when ref_cursor%notfound;
dbms_output.put_line('第一级:'|| m1 || ',第二级:' || m2 || ',第三级:'|| m3) ;
end loop;
close ref_cursor;
dbms_output.put_line(totalcount);
end;
附上表数据结构图:
客户端调用方法如下图: