--集合实现游标查询 CREATE OR REPLACE PACKAGE emppkg IS TYPE t_record IS RECORD( rn INT, empno emp.empno%TYPE, ename emp.ename%TYPE, sal emp.sal%TYPE, deptno emp.deptno%TYPE); TYPE emplist IS TABLE OF t_record;--定义返回结果的记录集合类型 --定义实现分页显示的过程 PROCEDURE sp_page( p_page_size IN OUT INT,--每页输出显示的记录数 p_cur_page_no IN OUT INT,--当前页码 p_outcollection OUT emplist--接收查询返回结果 ); END emppkg; / CREATE OR REPLACE PACKAGE BODY emppkg IS PROCEDURE sp_page( p_page_size IN OUT INT,--每页输出记录数 p_cur_page_no IN OUT INT,--当前页码 p_outcollection OUT emplist--接收查询返回值 ) IS v_start_rownum NUMBER; v_end_rownum NUMBER; v_total_records NUMBER; v_total_pages NUMBER; indexvalue BINARY_INTEGER :=1; BEGIN --查询记录总数 SELECT COUNT(*) INTO v_total_records FROM emp; --验证输入页面显示记录数量,确保大于0 IF p_page_size < 0 THEN p_page_size :=10; END IF; --计算页面总数 IF MOD(v_total_records,v_total_pages) = 0 THEN v_total_pages := v_total_records / p_page_size; ELSE v_total_pages := (v_total_records / p_page_size)+1; END IF; --验证页号 IF p_cur_page_no < 1 THEN p_cur_page_no := 1; END IF; IF p_cur_page_no > v_total_pages THEN p_cur_page_no := v_total_pages; END IF; --执行分页查询 --计算当前页开始显示的记录在整个记录中从哪开始 v_start_rownum := (p_cur_page_no-1)*p_page_size+1; --计算当前页的最后一条记录位于哪 v_end_rownum := p_cur_page_no*p_page_size; --构造初始化记录嵌套表 p_outcollection := emplist(); --查询记录 FOR v_emp IN (SELECT * FROM (SELECT ROWNUM rn,empno,ename,sal,deptno FROM (SELECT empno,ename,sal,deptno FROM emp WHERE sal IS NOT NULL ORDER BY sal) A--选出有sal的作为表A WHERE ROWNUM<=v_end_rownum) B WHERE rn>=v_start_rownum)--在B中筛选去掉当前页之前的所有记录 LOOP--循环把取出的数赋给接收变量 p_outcollection.EXTEND; p_outcollection(indexvalue):=v_emp; indexvalue:=indexvalue+1; END LOOP; END sp_page; END emppkg; / --游标实现分页查询 CREATE OR REPLACE PACKAGE curspkg IS TYPE query_cursor IS REF CURSOR; PROCEDURE sp_page( p_page_size IN OUT INT,--每页输出记录数 p_cur_page_no IN OUT INT,--当前页码 p_sql_select VARCHAR2,--查询语句,包含排序部分 p_total_pages OUT INT,--返回总页数 p_total_records OUT INT,--返回总记录数 p_out_cursor OUT query_cursor--接收返回当前页的数据集 ); END curspkg; / CREATE OR REPLACE PACKAGE BODY curspkg IS PROCEDURE sp_page( p_page_size IN OUT INT,--每页输出记录数 p_cur_page_no IN OUT INT,--当前页码 p_sql_select VARCHAR2,--查询语句,包含排序部分 p_total_pages OUT INT,--返回总页数 p_total_records OUT INT,--返回总记录数 p_out_cursor OUT query_cursor--接收返回当前页的数据集 ) IS v_count_sql VARCHAR2(1000); v_start_rownum INT; v_end_rownum INT; v_sql VARCHAR2(4000); BEGIN --动态sql语句,调用输入的查询语句,计算输入的语句一共查询出多少数据 v_count_sql := 'SELECT TO_CHAR(COUNT(*)) FROM ('||p_sql_select||')'; EXECUTE IMMEDIATE v_count_sql INTO p_total_records; --验证输入页面显示记录数量,确保大于0 IF p_page_size < 0 THEN p_page_size :=10; END IF; --计算页面总数 IF MOD(p_total_records,P_total_pages) = 0 THEN P_total_pages := p_total_records / p_page_size; ELSE P_total_pages := (p_total_records / p_page_size)+1; END IF; --验证页号 IF p_cur_page_no < 1 THEN p_cur_page_no := 1; END IF; IF p_cur_page_no > P_total_pages THEN p_cur_page_no := P_total_pages; END IF; --执行分页查询 --计算当前页开始显示的记录在整个记录中从哪开始 v_start_rownum := (p_cur_page_no-1)*p_page_size+1; --计算当前页的最后一条记录位于哪 v_end_rownum := p_cur_page_no*p_page_size; v_sql:='SELECT * FROM (SELECT ROWNUM rn,A.* FROM ('||p_sql_select||') A WHERE ROWNUM<='||TO_CHAR(v_start_rownum)||') B WHERE rn>='||TO_CHAR(v_end_rownum); OPEN p_out_cursor FOR v_sql; END sp_page; END curspkg; /