查看: 61817|回复: 74

[精华] REF CURSOR 小结

[复制链接]
论坛徽章:
12
ITPUB元老
日期:2005-02-28 12:57:00福特
日期:2013-08-12 09:40:06迷宫蛋
日期:2013-06-03 13:48:41生肖徽章2007版:鸡
日期:2009-11-11 14:03:05BLOG每日发帖之星
日期:2009-06-17 01:01:03BLOG每日发帖之星
日期:2009-06-16 01:01:04生肖徽章2007版:龙
日期:2009-01-13 11:06:03参与2007年甲骨文全球大会(中国上海)纪念
日期:2007-08-06 15:19:02ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02会员2006贡献徽章
日期:2006-04-17 13:46:34
跳转到指定楼层
1#
发表于 2005-10-27 11:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
利用REF CURSOR,可以在程序间传递结果集(一个程序里打开游标变量,在另外的程序里处理数据)。
也可以利用REF CURSOR实现BULK SQL,提高SQL性能。


REF CURSOR分两种,Strong REF CURSOR 和 Weak REF CURSOR。


Strong REF CURSOR:指定retrun type,CURSOR变量的类型必须和return type一致。
DECLARE
TYPE strongcurtyp IS REF CURSOR RETURN emp%ROWTYPE;
emp_cv strongcurtyp;


Weak REF CURSOR:不指定return type,能和任何类型的CURSOR变量匹配。
DECLARE
TYPE weakcurtyp IS REF CURSOR;
weak_cv weakcurtyp;
any_cv SYS_REFCURSOR; --使用SYS_REFCURSOR可以使变量any_cv跟任何weak REF CURSOR类型匹配。
论坛徽章:
12
ITPUB元老
日期:2005-02-28 12:57:00福特
日期:2013-08-12 09:40:06迷宫蛋
日期:2013-06-03 13:48:41生肖徽章2007版:鸡
日期:2009-11-11 14:03:05BLOG每日发帖之星
日期:2009-06-17 01:01:03BLOG每日发帖之星
日期:2009-06-16 01:01:04生肖徽章2007版:龙
日期:2009-01-13 11:06:03参与2007年甲骨文全球大会(中国上海)纪念
日期:2007-08-06 15:19:02ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02会员2006贡献徽章
日期:2006-04-17 13:46:34
2#
 楼主| 发表于 2005-10-27 11:35 | 只看该作者

使用Strong REF CURSOR例子

CREATE OR REPLACE PACKAGE emp_data AS
TYPE empcurtyp IS REF CURSOR RETURN emp%rowtype; --定义TYPE as Strong REF CURSOR
PROCEDURE open_emp_cv(emp_cv IN OUT empcurtyp, choice INT); --根据不同的choice选择不同的CURSOR
PROCEDURE retrieve_data(choice INT); --通过调用procedure open_emp_cv,返回指定的结果集。
END emp_data;


=============================================




CREATE OR REPLACE PACKAGE BODY emp_data AS

--procedure open_emp_cv-----------------------------

PROCEDURE open_emp_cv(emp_cv IN OUT empcurtyp, choice INT) IS --emp_cv作为传入/传出的CURSOR PARAMETER
BEGIN
IF choice = 1 THEN
OPEN emp_cv FOR
SELECT * FROM emp WHERE empno < 7800;
ELSIF choice = 2 THEN
OPEN emp_cv FOR
SELECT * FROM emp WHERE SAL < 1000;
ELSIF choice = 3 THEN
OPEN emp_cv FOR
SELECT * FROM emp WHERE ename like 'J%';
END IF;
END;


--procedure retrieve_data----------------------------------

PROCEDURE retrieve_data(choice INT) IS
return_cv empcurtyp; --定义传入open_emp_cv的CURSOR变量
return_row emp%ROWTYPE;
invalid_choice EXCEPTION;
BEGIN
open_emp_cv(return_cv, choice); --调用 procedure OPEN_EMP_CV

IF choice = 1 THEN
DBMS_OUTPUT.PUT_LINE('EMPLOYEES with empno less than 7800');
ELSIF choice = 2 THEN
DBMS_OUTPUT.PUT_LINE('EMPLOYEES with salary less than 1000');
ELSIF choice = 3 THEN
DBMS_OUTPUT.PUT_LINE('EMPLOYEES with name starts with ''J''');
ELSE
RAISE invalid_choice;
END IF;

LOOP
FETCH return_cv
INTO return_row;
EXIT WHEN return_cv%NOTFOUND;

DBMS_OUTPUT.PUT_LINE(return_row.empno || '--' || return_row.ename || '--' ||
return_row.sal);
END LOOP;

EXCEPTION
WHEN invalid_choice THEN
DBMS_OUTPUT.PUT_LINE('The CHOICE should be in one of (1,2,3)!');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Errors in procedure RETRIEVE_DATA!');
END;

END emp_data;


================================




执行:
SQL> EXEC emp_data.retrieve_data(1);
EMPLOYEES with empno less than 7800
7369--SMITH--800
7499--ALLEN--1600
7521--WARD--1250
7566--JONES--2975
7654--MARTIN--1250
7698--BLAKE--2850
7782--CLARK--2450
7788--SCOTT--3000
PL/SQL procedure successfully completed

SQL> EXEC emp_data.retrieve_data(2);
EMPLOYEES with salary less than 1000
7369--SMITH--800
7900--JAMES--950
PL/SQL procedure successfully completed

SQL> EXEC emp_data.retrieve_data(3);
EMPLOYEES with name starts with 'J'
7566--JONES--2975
7900--JAMES--950
PL/SQL procedure successfully completed

SQL> EXEC emp_data.retrieve_data(34);
The CHOICE should be in one of (1,2,3)!
PL/SQL procedure successfully completed

使用道具 举报

回复
论坛徽章:
12
ITPUB元老
日期:2005-02-28 12:57:00福特
日期:2013-08-12 09:40:06迷宫蛋
日期:2013-06-03 13:48:41生肖徽章2007版:鸡
日期:2009-11-11 14:03:05BLOG每日发帖之星
日期:2009-06-17 01:01:03BLOG每日发帖之星
日期:2009-06-16 01:01:04生肖徽章2007版:龙
日期:2009-01-13 11:06:03参与2007年甲骨文全球大会(中国上海)纪念
日期:2007-08-06 15:19:02ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02会员2006贡献徽章
日期:2006-04-17 13:46:34
3#
 楼主| 发表于 2005-10-27 13:12 | 只看该作者

使用Weak REF CURSOR例子

--procedure open_cv---------------------------------------

create or replace procedure open_cv(choice IN INT,
return_cv OUT SYS_REFCURSOR) is
--参数return_cv为weak REF CURSOR,利用SYS_CURSOR来定义
begin
if choice = 1 then
open return_cv for 'select * from emp';
elsif choice = 2 then
open return_cv for 'select * from dept';
end if;
end open_cv;


--procedure retrieve_data------------------------------------

create or replace procedure retrieve_data(choice IN INT) is
emp_rec emp%rowtype;
dept_rec dept%rowtype;
return_cv SYS_REFCURSOR;
invalid_choice exception;
begin
if choice=1 then
dbms_output.put_line('employee information');
open_cv(1,return_cv); --调用procedure open_cv;
loop
fetch return_cv into emp_rec;
exit when return_cv%notfound;
dbms_output.put_line(emp_rec.empno||'-'||emp_rec.ename||'-'||emp_rec.sal);
end loop;
elsif choice=2 then
dbms_output.put_line('department information');
open_cv(2,return_cv);
loop
fetch return_cv into dept_rec;
exit when return_cv%notfound;
dbms_output.put_line(dept_rec.deptno||'-'||dept_rec.dname||'-'||dept_rec.loc);
end loop;
else
raise invalid_choice;
end if;

exception
when invalid_choice then
dbms_output.put_line('The CHOICE should be one of 1 and 2!');
when others then
dbms_output.put_line('Errors in procedure retrieve_data');
end retrieve_data;

-----------------------------------------------------------------

执行:
SQL> exec retrieve_data(1);
employee information
7369-SMITH-800
7499-ALLEN-1600
7521-WARD-1250
7566-JONES-2975
7654-MARTIN-1250
7698-BLAKE-2850
......
PL/SQL procedure successfully completed

SQL> exec retrieve_data(2);
department information
10-ACCOUNTING-NEW YORK
20-RESEARCH-DALLAS
30-SALES-CHICAGO
40-OPERATIONS-BOSTON
PL/SQL procedure successfully completed

使用道具 举报

回复
论坛徽章:
12
ITPUB元老
日期:2005-02-28 12:57:00福特
日期:2013-08-12 09:40:06迷宫蛋
日期:2013-06-03 13:48:41生肖徽章2007版:鸡
日期:2009-11-11 14:03:05BLOG每日发帖之星
日期:2009-06-17 01:01:03BLOG每日发帖之星
日期:2009-06-16 01:01:04生肖徽章2007版:龙
日期:2009-01-13 11:06:03参与2007年甲骨文全球大会(中国上海)纪念
日期:2007-08-06 15:19:02ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02会员2006贡献徽章
日期:2006-04-17 13:46:34
4#
 楼主| 发表于 2005-10-27 13:15 | 只看该作者

用REF CURSOR实现BULK功能

1. To speed up INSERT, UPDATE, and DELETE statements, enclose the SQL statement within a PL/SQL FORALL statement instead of a loop construct.
2. To speed up SELECT statements, include the BULK COLLECT INTO clause in the SELECT statement instead of using INTO.



SQL> create table tab2 as select empno ID, ename NAME, sal SALARY from emp where 1=2;
Table created


-------------------------------------------------------

create or replace procedure REF_BULK is
type empcurtyp is ref cursor;
type idlist is table of emp.empno%type;
type namelist is table of emp.ename%type;
type sallist is table of emp.sal%type;

emp_cv empcurtyp;
ids idlist;
names namelist;
sals sallist;

row_cnt number;
begin
open emp_cv for
select empno, ename, sal from emp;
fetch emp_cv BULK COLLECT
INTO ids, names, sals; --BULK COLLECT INTO instead of INTO
close emp_cv;

for i in ids.first .. ids.last loop
dbms_output.put_line('id=' || ids(i) || ' name=' || names(i) ||
' salary=' || sals(i));
end loop;

forall i in ids.first .. ids.last --FORALL instead of FOR ...LOOP
insert into tab2 values (ids(i), names(i), sals(i));
commit;

select count(*) into row_cnt from tab2;
dbms_output.put_line('-----------------------------------');
dbms_output.put_line('The row number of tab2 is ' || row_cnt);
end REF_BULK;


------------------------------------------------------------

执行:

SQL> exec ref_bulk;

id=7369 name=SMITH salary=800
id=7499 name=ALLEN salary=1600
id=7521 name=WARD salary=1250
id=7566 name=JONES salary=2975
id=7654 name=MARTIN salary=1250
id=7698 name=BLAKE salary=2850
id=7782 name=CLARK salary=2450
id=7788 name=SCOTT salary=3000
id=7839 name=KING salary=5000
id=7844 name=TURNER salary=1500
id=7876 name=ADAMS salary=1100
id=7900 name=JAMES salary=950
id=7902 name=FORD salary=3000
id=7934 name=MILLER salary=1300
-----------------------------------
The row number of tab2 is 14

PL/SQL procedure successfully completed

使用道具 举报

回复
论坛徽章:
73
蒙奇·D·路飞
日期:2016-10-28 11:39:37马上有车
日期:2014-11-25 14:43:37马上有车
日期:2014-11-12 14:25:48itpub13周年纪念徽章
日期:2014-09-30 11:14:30itpub13周年纪念徽章
日期:2014-09-29 15:19:13itpub13周年纪念徽章
日期:2014-09-28 10:55:55祖国65周年纪念徽章
日期:2014-09-26 17:05:18马上有钱
日期:2014-03-22 22:02:03夏利
日期:2013-07-29 11:37:58紫蛋头
日期:2013-07-15 13:41:33
5#
发表于 2005-10-27 15:58 | 只看该作者
很全面!这个REF CUOSOR在oracle开发中比较有用。

使用道具 举报

回复
招聘 : 数据库管理员
论坛徽章:
38
ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14现任管理团队成员
日期:2012-10-18 17:11:21版主4段
日期:2012-05-15 15:24:112012新春纪念徽章
日期:2012-02-13 15:09:232012新春纪念徽章
日期:2012-02-13 15:09:232012新春纪念徽章
日期:2012-02-13 15:09:23
6#
发表于 2005-10-27 19:16 | 只看该作者
总结得好,呵呵,精华

使用道具 举报

回复
论坛徽章:
1
蛋疼蛋
日期:2013-07-01 10:58:49
7#
发表于 2005-10-28 11:51 | 只看该作者
very good!

使用道具 举报

回复
论坛徽章:
113
itpub13周年纪念徽章
日期:2014-10-08 15:15:25itpub13周年纪念徽章
日期:2014-10-08 15:15:25马上加薪
日期:2015-01-05 10:58:56暖羊羊
日期:2015-06-15 17:17:24喜羊羊
日期:2015-06-24 17:12:15
8#
发表于 2005-10-28 11:55 | 只看该作者
好帖!很有启发!谢

使用道具 举报

回复
论坛徽章:
7
数据库板块每日发贴之星
日期:2005-05-23 01:01:21授权会员
日期:2005-10-30 17:05:332009新春纪念徽章
日期:2009-01-04 14:52:282010新春纪念徽章
日期:2010-03-01 11:20:002011新春纪念徽章
日期:2011-02-18 11:43:332012新春纪念徽章
日期:2012-01-04 11:49:54
9#
发表于 2005-10-29 16:24 | 只看该作者
使用Weak REF CURSOR例子 這種可以用 form中嗎?

使用道具 举报

回复
招聘 : 系统架构师
论坛徽章:
372
双子座
日期:2015-08-18 12:18:21摩羯座
日期:2015-09-20 17:10:27秀才
日期:2015-09-21 09:46:16秀才
日期:2015-09-21 11:16:42秀才
日期:2015-10-08 17:57:58天枰座
日期:2015-10-28 18:28:29秀才
日期:2015-11-11 09:48:44秀才
日期:2015-11-11 10:07:14秀才
日期:2015-11-11 10:22:49秀才
日期:2015-09-11 10:43:06
10#
发表于 2005-10-30 10:35 | 只看该作者
Good

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表