一、游标:
游标的概念:
游标的作用是临时存储从数据库中提取的数据块,由系统或者用户以变量的形式定义,是sql的内存工作区;
//
分为两种类型:显式游标和隐式游标
隐式游标
系统定义和管理的,像DML(insert,delete,update)操作和单行SELECT(select…into…)语句会使用隐式游标;
显式游标
用户自己定义的,分为4个步骤:
1、声明游标
在DECLARE部分,按照以下格式声明游标:
CURSOR 游标名[参数1 数据类型[,参数2 数据类型]]
IS SELECT语句;
参数是可选部分,如果定义了参数,必须在调用时传入实际的参数,后面的select语句可以是对表、视图等的查询,甚至是联合查询,可以带WHERE 条件、ORDER BY或GROUP BY子句,但不能使用INTO子句,在SELECT 语句中可以使用定义在游标之前定义的变量。
2、打开游标
在可执行部分,按照以下格式打开游标:
OPEN 游标名[实际参数1[,实际参数2]];
3、提取数据
在可执行部分,按照以下格式将游标工作区中的数据取到变量中:
FETCH 游标名 INTO 变量名1[,变量名2]

FETCH 游标名 INTO 记录变量
FETCH语句一次返回一行数据,要返回多行数据,需要使用循环
定义记录变量的方法如下:
变量名 表名/游标名%ROWTYPE;
其中表名必须存在,游标名也必须先定义。
4、关闭游标
CLOSE 游标名;
显示游标打开后必须显式关闭。

-- 游标%属性     返回值类型   意义
%ROWCOUNT       整型      获得FETCH语句返回的数据行数;
%FOUNG          布尔型     最近的fetch返回一行数据则为真,否则为假;
%notfount       布尔型     与%found属性相反
%isopen         布尔型     游标打开则为真,否则为假

二、游标变量
像游标CURSOR一样,游标变量REF CURSOR指向指定查询结果集的当前行,区别就是可以先声明而不用绑定查询,使用起来更灵活;
游标变量没有参数。
1、声明格式
DECLARE
TYPE 游标变量名 IS REF CURSOR;
可以分为强类型和弱类型
TYPE 游标变量名 IS REF CURSOR RETURN 表名%ROWTYPE — 强类型
TYPE 游标变量名 IS REF CURSOR ---- 弱类型

练习:


-- 1、使用变量
declare                                           -- 声明部分v_ename varchar2(10);v_job varchar2(10);cursor cur_emp isselect ename,job from emp where empno = 7788;
begin                                             -- 执行部分open cur_emp;                                   -- 打开游标fetch cur_emp                                   -- 提取数据into v_ename,v_job;dbms_output.put_line(v_ename || ',' || v_job);close cur_emp;                                  -- 关闭游标
end;
-- 2、使用记录变量
-- 定义记录变量的格式:1、变量名 表名/游标名;2、表名必须存在,游标名也必须先定义
declareemp_record emp%rowtype;  -- 定义记录型变量cursor cur_emp isselect * from emp where empno = 7788;
beginopen cur_emp;fetch cur_empinto emp_record;dbms_output.put_line(emp_record.ename || ',' || emp_record.job);close cur_emp;
end;
-- 3、使用循环
declareemp_record emp%rowtype;i          number := 0;cursor cur_emp isselect * from emp order by sal desc;
beginopen cur_emp;while (i < 3) loopi := i + 1;fetch cur_empinto emp_record;dbms_output.put_line(emp_record.ename || ',' || emp_record.sal);end loop;close cur_emp;
end;
-- 4、带参游标
declareemp_record emp%rowtype;cursor cur_emp(p_deptno emp.deptno%type, p_job emp.job%type) is -- 不要忘了定义参数的数据类型,但是可以不写数据长度select *from empwhere deptno = p_deptnoand job = p_job;
beginopen cur_emp(20, 'CLERK');loopfetch cur_empinto emp_record;exit when cur_emp%notfound; -- 注意exit语句的位置,放在下面的结果就是错误的dbms_output.put_line(emp_record.ename);-- exit when cur_emp%notfound;end loop;close cur_emp;
end;
--5、动态select语句和动态游标(游标变量)的用法-- 5.1、动态select语句-- 语法:execute immediate 查询语句字符串 into 变量1【变量2……】;
declarev_ename emp.ename%type;sqlstr  varchar2(100);
beginsqlstr := 'select ename from emp where empno=7788';-- 定义查询字符串execute immediate sqlstrinto v_ename;dbms_output.put_line(v_ename);
end;-- 5.2、动态游标(游标变量)/* 1、定义游标类型:TYPE 游标类型名 IS REF CURSOR;2、声明游标变量:游标变量名  游标类型名;3、在可执行部分可以如下形式打开一个动态游标:OPEN 游标变量名 FOR 查询语句字符串;*/declaretype cur_type is ref cursor;cur_emp    cur_type;emp_record emp%rowtype;letter     char := 'A';-- 注意此处别指定长度,如char(2),则letter=(A+空格),数据库查不到名字str        varchar2(100);
beginloopstr := 'select ename from emp where ename like ''%' || letter || '%''';dbms_output.put_line('包含字母' || letter || '的名字');open cur_emp for str; -- 此处不要忘了加 for strloopfetch cur_empinto emp_record.ename; -- 注意此处提取的值只是ename这一列,因为select语句中只查询了这一列exit when cur_emp%notfound;dbms_output.put_line(emp_record.ename);end loop;exit when letter = 'Z'; -- 此处是“=”,不是“:=”letter := chr(ascii(letter) + 1);-- CHR函数和ASCII函数end loop;close cur_emp;
end;-- 6、异常处理/*1、位置:可执行部分之后,由WHEN引导的多个分支构成2、语法:WHEN 错误1【OR错误2】THEN 语句序列1;WHEN 错误2【OR错误3】THEN语句序列2;WHEN OTHERS语句序列n;END;*/
-- 6.1、系统预定义declarev_name emp.ename%type;type cur_type is ref cursor;cur_emp cur_type;--cur_emp(p_empno emp.empno%type) cur_type; 游标变量没有参数,而游标有,所以这里带参数是错误的str varchar2(100);beginstr := 'select ename from emp where empno=&a'; --如果这里是部门号,最好加上一个loop循环,一个部门不止一个人open cur_emp for str;fetch cur_empinto v_name;dbms_output.put_line(v_name);exceptionwhen no_data_found thendbms_output.put_line('输入的编号不存在');-- 了解no_data_found触发的条件,空值不代表异常,上面游标直接返回了空值,所以不会触发此异常,但是如果改写上方的str会触发下面others异常when others thendbms_output.put_line('jhj');close cur_emp;end;
-- 6.2自定义异常(语法一)/*语法:declare错误名 exception;pragma exception_init(错误名,-错误代码);*/declareNO_EMPNO exception;pragma exception_init(NO_EMPNO, -1400);-- 此处错误代码是-1400begin-- update emp set ename='haha' where empno=&i;  更新0行,返回空值,所以不会报异常insert into emp(empno) values (null);exceptionwhen NO_EMPNO thendbms_output.put_line('输入的部门编号不存在');end;
-- 6.2自定义异常(语法二)
/*定义的语法:错误名 exception;触发的语法:raise 错误名;
*/
declareno      number := &i;v_ename emp.ename%type;error1 exception;error2 exception;
begininsert into emp (empno, ename) values (no, 'haha');if no > 10 thenraise error1;elsif no < 10 thenraise error2;end if;
exceptionwhen error1 thenrollback;dbms_output.put_line('编号大于10');when error2 thencommit;dbms_output.put_line('编号小于10');
end;
-- 6.3、自定义异常(语法三)
/*raise_application_error 函数的用法错误码的范围20000-20999不用预先定义异常名
*/
declareno number := &i;
begininsert into emp (empno, ename) values (no, 'hah');if no > 10 thencommit; -- 注意commit的位置,如果放在下面就执行不到,先捕获异常,下方的rollback同理raise_application_error(-20001, '编号大于10');-- commit;elsif no < 10 thenrollback;raise_application_error(-20002, '编号小于10');-- rollback;end if;
end;
--7、隐性变量及未定义游标的循环
beginfor i in (select ename, sal from emp) loop-- 隐含了记录变量i的定义,隐含了游标的定义、打开、提取、关闭dbms_output.put_line('雇员的名字是:' || rpad(i.ename, 10, ' ') ||rpad('*', i.sal / 100, '*')); -- rpad函数,语法:rpad('tech', 7); 将返回'tech '   -- rpad('tech', 2); 将返回'te'   -- rpad('tech', 8, '0'); 将返回'tech0000'-- 注意此处不能是下方的写法-- dbms_output.put_line('雇员的名字是:'||rpad(emp.ename,10,' ')||rpad('*',emp.sal/100,'*'));end loop;
end;
-- 8、练习
-- 8.1
declarev_count number := 0;
begindbms_output.put_line('----部门信息----');dbms_output.put_line('-------------');for emp_record in (select * from emp) loopdbms_output.put_line('部门编号:' || emp_record.deptno);dbms_output.put_line('员工姓名:' || emp_record.ename);dbms_output.put_line('员工工资:' || emp_record.sal);v_count := v_count + 1;end loop;dbms_output.put_line('部门数:' || v_count);end;
-- 8.2、编写程序,统计输出部门名称、部门总人数、总工资和部门经理
declarev_deptno emp.deptno%type;v_ename  emp.ename%type;v_dname  dept.dname%type;v_count  number;v_sum    number;cursor cur_emp isselect e.deptno, count(1), sum(e.sal) from emp e group by e.deptno;
beginopen cur_emp;dbms_output.put_line('-------------------部门信息------------------');dbms_output.put_line(rpad('部门名称', 12) || rpad('部门总人数', 12) ||rpad('总工资', 12) || rpad('部门经理', 12));loopfetch cur_empinto v_deptno, v_count, v_sum;-- 注意此处值一定要和select语句查询的对象一一对应,否则报错ORA_06502(数字或值错误:数值精度太高)exit when cur_emp%notfound;select enameinto v_enamefrom empwhere deptno = v_deptnoand job = 'MANAGER';select dname into v_dname from dept where deptno = v_deptno;dbms_output.put_line(rpad(v_dname, 16) || rpad(to_char(v_count), 9) ||rpad(to_char(v_sum), 13) || rpad(v_ename, 6));-- 可以用rpad函数格式化表,字符类型时数字的一定要转换为字符(to_char)end loop;close cur_emp;dbms_output.put_line('---------------------------------------------');
end;
-- 8.3、为雇员增加工资,从工资低的雇员开始,为每个人增加原工资的10%,限定所增加的工资总额为800元,显示增加工资的人数和余额
declarev_sal   number;s_sal   number := 800;v_count number := 0;v_ename emp.ename%type;cursor cur_emp isselect ename, sal from temp_emp order by sal asc;
beginopen cur_emp;dbms_output.put_line('人员' || '   ' || '原工资' || '  ' || '增加后的工资');dbms_output.put_line('----------------------');loop-- 此处漏写了loop一直报错,找了半天fetch cur_empinto v_ename, v_sal;exit when cur_emp%notfound;if s_sal >= 0.1 * v_sal thens_sal := s_sal - 0.1 * v_sal;update temp_emp set sal=1.1*v_sal where sal=v_sal;v_count := v_count + 1;-- exit when s_sal >= 800;-- 利用此种方法退出循环不行dbms_output.put_line(rpad(v_ename, 9) || rpad(to_char(v_sal), 8) || '  ' ||rpad(to_char(1.1 * v_sal), 8));else-- 此处不能是eslif,否则报错dbms_output.put_line(rpad(v_ename, 9) || rpad(to_char(v_sal), 8) || '  ' ||rpad(to_char(v_sal), 8));end if;end loop;dbms_output.put_line('增加工资的人数:' || v_count);dbms_output.put_line('余额:' || s_sal);close cur_emp;commit;
end;

Oracle游标和游标变量相关推荐

  1. Oracle存储过程以及游标

    一.存储过程 1.存储过程定义 所谓存储过程(Stored Procedure),就是一组用于完成特定数据库功能的SQL语句集,该SQL语句集经过 编译后存储在数据库系统中.在使用时候,用户通过指定已 ...

  2. Oracle隐式游标和显式游标

    游标是什么?就是在内存开辟的一块临时存储空间. 1.Oracle隐式游标 1.1Oracle有常用的哪些隐式游标 1.2 Oracle隐式游标演示 -- 隐式游标 (使用的表为Oracle默认自带的e ...

  3. 小青蛙oracle跟踪,Oracle 存储过程:游标

    一.认识游标 什么是游标?游标是数据库的一种数据类型,它用来管理从数据源(表,视图等)获取到的数据结果集,可以想象成一个游动的光标(指针),指向一个结果集,通过游标的移动逐行提取每一行的记录,就像我们 ...

  4. oracle中创建游标,oracle 存储过程创建游标

    Oracle与Sql Server差异点详解 1.create函数或存储过程异同点 Oracle 创建函数或存储过程一般是 create or replace -- SQL SERVER 则是在创建之 ...

  5. oracle 如何创建游标,Oracle--plsql游标创建和使用

    Oracle--plsql游标创建和使用 为什么要游标: 先看这个: DECLARE v_empno emp.empno%type; v_ename emp.ename%type; BEGIN SEL ...

  6. oracle 游标内存自动释放,详解Oracle隐式游标和显式游标

    游标是什么?就是在内存开辟的一块临时存储空间. 1.Oracle隐式游标 1.1Oracle有常用的哪些隐式游标 1.2 Oracle隐式游标演示 -- 隐式游标 (使用的表为Oracle默认自带的e ...

  7. oracle中的cursor属性有哪些,Oracle学习11:游标(cursor)--显式游标隐式游标、游标四个属性、循环遍历...

    1.概述 上文PLSQL学习中提到的知识,可以发现,基本都可以通过Java等语言实现,而为了实现程序的可移植性,实际开发工作中我们也是如此做的. 那么PLSQL的重点是什么呢?接下来我们来介绍游标cu ...

  8. (七)Oracle学习笔记—— 游标

    1.游标简介 游标用来处理从数据库中检索的多行记录(使用SELECT语句).利用游标,程序可以逐个地处理和遍历一次检索返回的整个记录集. 为了处理SQL语句,Oracle将在内存中分配一个区域,这就是 ...

  9. Oracle中cursor(游标)总结

    1.       游标: 容器,存储SQL语句影响行数. 2.       游标类型: 隐式游标,显示游标,REF游标.其中,隐式游标和显示游标属于静态游标(运行前将游标与SQL语句关联),REF游标 ...

最新文章

  1. IIC通信控制的AD5259------在调试过程中遇到的奇葩问题
  2. RabbitMQ的安装(linux篇)
  3. 五、JavaScript基础知识,学会操作元素的简单事件(一)
  4. python创建一个空的dataframe_python 创建一个空dataframe 然后添加行数据的实例
  5. How to check bad fix
  6. Sting中方法举例
  7. 大数据学习笔记24:利用MR改造Zebra项目
  8. Log42j 源代码分析:plugin(插件)机制
  9. jax-ws使用教程_JAX-WS教程
  10. java删除文件夹的方法
  11. 【<咩咩启示录>中的距骨骰低配版】
  12. SQL内连接和外连接的区别、where和on的区别详细介绍
  13. 图解等差数列和等比数列求和公式
  14. Ubuntu20.04 系统搭建 NetBox(开源 IPAM/DC 管理工具)
  15. 邮件撤回怎么操作?个人邮箱Outlook登录入口在哪?
  16. 解决windows防火墙拦截FTP连接
  17. 详细介绍idm下载以及配置,实现百度网盘急速下载不是梦,适合新手
  18. FinalShell密码找回/FinalShell密码破解
  19. linkedlist链表结构原理
  20. Java反射系列--Type接口及其子接口

热门文章

  1. Python~小程序
  2. java基于springboot社区养老服务管理系统附源码
  3. 机器自动翻译古文拼音 - 十大宋词 - ALL
  4. 无法附加到进程。Visual Studio 2015 远程调试器(MSVSMON.EXE)似乎没有在远程计算机上运行。
  5. 如何办理医疗器械经营许可证?
  6. 为什么Aruba始终走在网络世界的前列?
  7. 南京中医药大学本科毕业论文答辩和论文选题PPT模板
  8. 比微信封堵多闪、聊天宝和马桶MT的竞争更残酷 AToken仍然耸立链圈不倒
  9. 创新型服务“智能推荐”——互联网平台建设 1
  10. 锂号称“稀有金属”,关于它你不知道的知识,带你了解化学元素