--集合实现游标查询
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;
/