设为首页 收藏本站
查看: 832|回复: 0

[经验分享] Oracle_PL_ SQL_ 教程:游标

[复制链接]

尚未签到

发表于 2016-7-19 12:37:48 | 显示全部楼层 |阅读模式
--######################################--
--游标
--王林 2012.07.06
--######################################--
/*
游标的作用就是用于临时存储从数据库中提取的数据块。在某些情况下,需要把数据从存放在磁盘的表中调到计算机内存中进行处理,最后将处理结果显示出来或最终写回数据库。这样数据处理的速度才会提高,否则频繁的磁盘数据交换会降低效率。
游标有两种类型:显式游标和隐式游标。在前述程序中用到的SELECT...INTO...查询语句,一次只能从数据库中提取一行数据,对于这种形式的查询和DML操作,系统都会使用一个隐式游标。但是如果要提取多行数据,就要由程序员定义一个显式游标,并通过与游标有关的语句进行处理。显式游标对应一个返回结果为多行多列的SELECT语句。
游标一旦打开,数据就从数据库中传送到游标变量中,然后应用程序再从游标变量中分解出需要的数据,并进行处理。
对游标的操作包含四个部分:定义、打开、读取、关闭。
*/
--######################################--
--准备练习用表
CREATE TABLE wl_emp
AS
SELECT * FROM scott.emp;
--
SELECT * FROM wl_emp;
--######################################--
--一般游标
CREATE OR REPLACE PROCEDURE promotion_review_1
IS
nemployeeid NUMBER;
dstartdate  DATE;
denddate    DATE;
sjobid      VARCHAR2 (20);
CURSOR cselectjob
IS
SELECT a.empno
, a.hiredate
, a.hiredate
, a.job
FROM wl_emp a;
BEGIN
OPEN cselectjob;
LOOP
FETCH cselectjob INTO nemployeeid
, dstartdate
, denddate
, sjobid ;
EXIT WHEN cselectjob%NOTFOUND;
DBMS_OUTPUT.put_line( 'Employee '
|| nemployeeid
|| ' has job '
|| sjobid
|| ' for '
|| (denddate - dstartdate)
|| ' days.'
);
END LOOP;
CLOSE cselectjob;
END;
--######################################--
--FOR游标
CREATE OR REPLACE PROCEDURE promotion_review_2
IS
CURSOR cselectjob
IS
SELECT a.empno
, a.hiredate dstartdate
, a.hiredate denddate
, a.job
FROM wl_emp a;
BEGIN
FOR jh_rec IN cselectjob LOOP
DBMS_OUTPUT.put_line( 'Employee '
|| jh_rec.empno
|| ' had job '
|| jh_rec.job
|| ' for '
|| (jh_rec.dstartdate - jh_rec.denddate)
|| ' days.'
);
END LOOP;
END;
--######################################--
--隐式游标
/*
隐式游标的%ISOPEN属性始终为FALSE,因为没有打开显示游标。为了访问隐式游标的属性可以使用SQL%attribute引用最近执行的隐式游标。
任何执行块或异常块中的DML语句都是隐式游标。它包括INSERT、UPDATE和DELETE语句。
在组合使用SELECT语句与INTO或BULK COLLECT INTO语句,或是在游标FOR循环语句中潜入SELECT语句时,也可以创建隐式游标。
PL/SQL块中的每条SQL语句实际上都是隐式游标。通过DML主句后使用%ROWCOUNT特性,可知道任何语句所改变的行数。
也可以对SELECT语句查询返回的行数。
*/
CREATE OR REPLACE PROCEDURE promotion_review_3
IS
nempno NUMBER;
CURSOR cselectjob
IS
SELECT a.empno
, a.hiredate dstartdate
, (a.hiredate + 1) denddate
, a.job
FROM wl_emp a;
BEGIN
SELECT COUNT(*)
INTO nempno
FROM wl_emp;
DBMS_OUTPUT.put_line( 'There are '
|| nempno
|| ' employee history records.'
);
FOR jh_rec IN cselectjob LOOP
DBMS_OUTPUT.put_line( 'Employee '
|| jh_rec.empno
|| ' had job '
|| jh_rec.job
|| ' for '
|| (jh_rec.denddate - jh_rec.dstartdate)
|| ' days.'
);
END LOOP;
END;
--######################################--
--REF游标
--动态显式游标
CREATE OR REPLACE PROCEDURE demo
IS
--局部变量的名称不能和列名相同,否则列名值会被替换而不是变量值。
n_low_no  NUMBER := 7369;
n_high_no NUMBER := 7654;
emp_rec   VARCHAR2(20);   
CURSOR c_selt_name
IS
SELECT a.ename
FROM scott.emp a
WHERE a.empno BETWEEN n_low_no AND n_high_no;
BEGIN
OPEN c_selt_name;
LOOP
FETCH c_selt_name INTO emp_rec;
EXIT WHEN c_selt_name%NOTFOUND;
DBMS_OUTPUT.put_line(emp_rec);
END LOOP;
END demo;
--使用输入参数
CREATE OR REPLACE PROCEDURE demo
IS  
n_low_no  NUMBER;
n_high_no NUMBER;
emp_rec   VARCHAR2(20);   
CURSOR c_selt_name
IS
SELECT a.ename
FROM scott.emp a
WHERE a.empno BETWEEN n_low_no AND n_high_no;
BEGIN
--将程序改变为使用输入参数。
n_low_no  := TO_NUMBER(NVL(&1,7364));
n_high_no := TO_NUMBER(NVL(&2,7655));
OPEN c_selt_name;
LOOP
FETCH c_selt_name INTO emp_rec;
EXIT WHEN c_selt_name%NOTFOUND;
DBMS_OUTPUT.put_line(emp_rec);
END LOOP;
END demo;
--使用形式参数
CREATE OR REPLACE PROCEDURE demo
IS
n_low_no  NUMBER;
n_high_no NUMBER;
emp_rec   VARCHAR2(20);
--游标中的这些变量没有物理大小,因为他们在运行时获得。   
CURSOR c_selt_name(low_id  NUMBER
, high_id NUMBER)
IS
--SELECT语句中的变量不再是局部变量,他们是游标的局部变量,由游标定义中的形式参数定义。
SELECT a.ename
FROM scott.emp a
WHERE a.empno BETWEEN low_id AND high_id;
BEGIN
--在程序运行的时候,输入&1和&2分别赋值给局部变量n_low_no和n_high_no。
n_low_no  := TO_NUMBER(NVL(&1,7364));
n_high_no := TO_NUMBER(NVL(&2,7655));
--局部变量成为打开游标时传递的实参,然后将实参赋给游标作用域的变量low_id和high_id。
OPEN c_selt_name (n_low_no , n_high_no);
LOOP
FETCH c_selt_name INTO emp_rec;
EXIT WHEN c_selt_name%NOTFOUND;
DBMS_OUTPUT.put_line(emp_rec);
END LOOP;
END demo;

  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-246375-1-1.html 上篇帖子: ORACLE 的if else 下篇帖子: ORACLE技术小整理
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表