涉及到表的处理请参看原表结构与数据  Oracle建表插数据等等

游标:

1、目的
解决“ select * ”返回空、多行记录问题
但凡select,就可能多行结果集,也就需要用游标
2、原理
多行记录放内存中,游标指向第一条
比如,培训:
书桌 —— 库 —— 一大堆书
书包 —— 内存 —— 三本书
上课 —— 游标 —— 一本一本取
3、特点

一条一条取,逐行处理

set serveroutput on;--开启显示内容

cursor for循环,显示所有的雇员号

declare
cursor c1 is
select pk_Employee_ID from tb_Employee;
begin
for i in c1 loop
dbms_output.put_line(i.pk_Employee_ID);
end loop;
end;
/

等效于下面这段

declare
begin
for i in (select pk_Employee_ID from tb_Employee) loop
dbms_output.put_line(i.pk_Employee_ID);
end loop;
end;
/

open cursor,显示所有的雇员号

declare
v_empno tb_Employee.pk_Employee_ID%type;
cursor c1 is
select pk_Employee_ID from tb_Employee;
begin
open c1;
loop
fetch c1 into v_empno;
exit when c1%notfound;
dbms_output.put_line(v_empno);
end loop;
close c1;
end;
/

等效于下面这段

declare
v_empno tb_Employee.pk_Employee_ID%type;
cursor c1 is
select pk_Employee_ID from tb_Employee;
begin
open c1;
while c1%isopen loop
fetch c1 into v_empno;
if c1%notfound then
close c1;
end if;
dbms_output.put_line(v_empno);
end loop;
end;
/

简单的显示游标,根据部门号得出部门中雇员的信息

declare
cursor cur is
select *from tb_Employee where deptno = 10;
v_emp cur%rowtype;
begin
if not cur%isopen then
open cur;
end if;
loop
fetch cur into v_emp;
exit when cur%notfound;
dbms_output.put_line('雇员名是:'||v_emp.ename||'工资是:'||v_emp.sal);
end loop;
close cur;
exception
when others then
if cur%isopen then
close cur;
end if;
end;
/

显示游标及游标for循环,查看对应部门的员工号

declare
cursor emp_cursor is
select pk_Employee_ID from tb_Employee
where deptno = 30;
begin
for emp_record in emp_cursor
loop
dbms_output.put_line(emp_record.pk_Employee_ID);
end loop;
end;
/

隐式游标,查看返回的行数

declare
empno tb_Employee.pk_Employee_ID%type;
begin
select pk_Employee_ID into empno -- 对于DML之select into
from tb_Employee
where pk_Employee_ID = 7788;
if sql%found then
dbms_output.put_line('有一行记录'); -- 用sql%found、sql%notfound判断是否返回一行记录
end if;
exception
when no_data_found then
dbms_output.put_line('查询返回空行'); -- 用no_data_found判断是否返回空行记录
when too_many_rows then
dbms_output.put_line('查询返回多行'); -- 用too_many_rows判断是否返回多行记录
end;
/
declare
empno tb_Employee.pk_Employee_ID%type;
begin
select pk_Employee_ID into empno
from tb_Employee
where pk_Employee_ID = 7788;
if sql%rowcount > 0 then
dbms_output.put_line('从表中选择了'||sql%rowcount||'行');
else
dbms_output.put_line('从表中未选择行');
end if;
end;
/

--常见异常
--CURSOR_ALREADY_OPEN

--DUP_VAL_ON_INDEX

--INVALID_CURSOR

--INVALID_NUMBER,当输入的数据有误时,例如类型有错,或触发该例外

--NO_DATA_FOUND

--TOO_MANY_ROWS,如果返回超过了一行,则会触发该错误

--ZERO_DIVIDE,例如2/0语句时,则会触发该错误

--VALUE_ERROR,执行赋值操作时,如果长度不足以容纳实际数据,则会触发该例外

--其他预定义例外

--LOGIN_DENIED,登录错误,如果账号密码不对应会出现这个错误

--NOT_LOGGED_ON,如果用户没有登录就执行dml操作,就会触发该例外

--STORAGE_ERROR,吐过超出了内存空间或是内存被损坏,就会触发该例外

--TIMEOUT_ON_RESOURCE,如果Oracle在等待资源时,出现了超时就会触发该例外

--非预定义例外

--自定义例外

动态游标,输入部门号,显示该部门所有员工姓名和他的工资

declare
type fj_emp_cursor is ref cursor;--定义游标类型fj_emp_cursor
test_cursor fj_emp_cursor;--定义游标变量
v_ename tb_Employee.ename%type;--定义变量
v_sal tb_Employee.sal%type;
begin
open test_cursor for select ename,sal from tb_Employee where deptno=&no;--执行,把test_cursor和一个select结合
loop--循环取出
fetch test_cursor into v_ename,v_sal;
dbms_output.put_line('雇员名是:'||v_ename||',工资是:'||v_sal);
--判断是否test_cursor是否为空
exit when test_cursor%notfound;
end loop;
end;
/

根据输入选项的不同,分别显示员工表、部门表的所有信息

declare
type cur_type is ref cursor; -- 弱类型游标
cur cur_type;
v_emp tb_Employee%rowtype;
v_dept tb_Department%rowtype;
selection varchar2(1) := upper('&选项');
begin
if selection = 'E' then
open cur for
'select * from tb_Employee';
loop
fetch cur into v_emp;
exit when cur%notfound;
dbms_output.put_line(v_emp.ename||':'||v_emp.sal);
end loop;
close cur;
elsif selection = 'newtype' then
open cur for
'select * from tb_Department';
loop
fetch cur into v_dept;
exit when cur%notfound;
dbms_output.put_line(v_dept.pk_Department_ID||':'||v_dept.dname);
end loop;
close cur;
else
null;
end if;
end;
/

在上面的基础上,如果某个雇员的工资低于3000元,就增加1000元

declare
cursor aaa is
select sal from tb_Employee
where sal < 3000 for update;
cursor bbb is
select * from tb_Employee;
begin
for v_sal in aaa
loop
update tb_Employee
set sal = sal + 1000
where current of aaa;
end loop;
for v_emp in bbb
loop
dbms_output.put_line(v_emp.ename||':'||v_emp.sal);
end loop;
end;
/

用强类型游标显示雇员姓名和工资

declare
type record_type is record(name varchar2(10), sal number); -- 记录类型
type cur_type is ref cursor return record_type; -- 强类型游标,将来必须返回record_type类型的结果集
emp_record record_type; -- 记录类型变量
emp_cur cur_type; -- 强类型游标变量
begin
open emp_cur for
select ename, sal from tb_Employee; -- 动态SQL两边的单引号可以省略,必须返回record_type类型的结果集
loop
fetch emp_cur into emp_record; -- 把record_type类型的结果集向record_type类型的变量中填充
exit when emp_cur%notfound;
dbms_output.put_line(emp_record.name||':'||emp_record.sal);
end loop;
close emp_cur;
end;
/

Oracle系列之游标的更多相关文章

  1. .Net程序员学用Oracle系列(27):PLSQL 之游标、异常和事务

    1.游标 1.1.游标属性 1.2.隐式游标 1.3.游标处理及案例 2.异常 2.1.异常类别 2.2.异常函数 2.3.异常处理及案例 3.事务 3.1.开始事务.结束事务 3.2.自治事务 3. ...

  2. .Net程序员学用Oracle系列(7):视图、函数、过程、包

    <.Net程序员学用Oracle系列:导航目录> 本文大纲 1.视图 1.1.创建视图 2.函数 2.1.创建函数 2.2.调用函数 3.过程 3.1.创建过程 3.2.调用过程 4.包 ...

  3. .Net程序员学用Oracle系列(25):触发器详解

    1.触发器理论 1.1.触发器的应用场景 1.2.触发器的类型 1.3.DML 触发器的触发顺序 2.触发器实战 2.1.创建触发器 2.1.1.创建 DML 触发器 2.1.2.创建 DDL 触发器 ...

  4. .Net程序员学用Oracle系列(26):PLSQL 之类型、变量和结构

    1.类型 1.1.属性类型 1.2.记录类型 2.变量 2.1.变量类型 2.2.变量定义 2.3.变量赋值 3.结构 3.1.顺序结构 3.2.选择结构 3.3.循环结构 4.总结 1.类型 在&l ...

  5. .Net程序员学用Oracle系列(28):PLSQL 之SQL分类和动态SQL

    1.SQL 语句分类 1.1.分类方法及类型 1.2.数据定义语言 1.3.数据操纵语言 1.4.其它语句 2.动态 SQL 理论 2.1.动态 SQL 的用途 2.2.动态 SQL 的语法 2.3. ...

  6. .Net程序员学用Oracle系列(7):视图、函数、存储过程、包

    1.视图 1.1.创建.删除及调用普通视图 1.2.高级视图介绍 2.函数 2.1.系统函数介绍 2.2.创建.删除及调用自定义函数 3.存储过程 3.1.创建.修改及删除存储过程 3.2.调用存储过 ...

  7. 【转】Oracle系列导航目录

    .Net程序员学用Oracle系列(1):导航目录 .Net程序员学用Oracle系列(2):准备测试环境 .Net程序员学用Oracle系列(3):数据库编程规范 .Net程序员学用Oracle系列 ...

  8. (转)oracle 存储过程 带游标作为OUT参数输出

    (转)oracle 存储过程 带游标作为OUT参数输出 存储过程返回OUT参数的游标 例子. 包中带过程 要自己定义一个type [cur_name] is ref cursor游标,返回的时候就直接 ...

  9. oracle 中的游标

    oracle 中的游标 通俗易懂的sql代码直接上! --简单的游标使用滴呀 --使用FOR OBJ IN OBJS LOOP ......END LOOP; DECLARE CURSOR C_JOB ...

随机推荐

  1. 再议Unity 3D

    一年前,偶发冲动,翻译了<[译] Unity3D游戏和facebook绑定(1:简介)>系列文章. 现在看有2个明显的好处, 一:给这个不温不火的博客带了top 3的人气: 二:我个人由此 ...

  2. POJ 1276 Cash Machine -- 动态规划(背包问题)

    题目地址:http://poj.org/problem?id=1276 Description A Bank plans to install a machine for cash withdrawa ...

  3. 解决在管理wordpress时权限不足的问题

    我的wordpress网站的运行环境是自己手动搭建的lamp环境,在管理wordpress时经常遇到因没有足够的权限而无法执行某些操作.在linux上的权限不足的问题无外乎有两个原因,一个是wordp ...

  4. 当linux遇上多网卡时

    我虚拟机有三个网卡,有两个在用,分别是不同的网段 eth4: 192.168.100.6/24 eth6: 192.168.137.131/24 但是默认系统把我的内部网络eth6设置为所有ip地址需 ...

  5. 【pano2vr】网页Flash中简单实现炫酷的3D模型制作

    花了两天时间学习如何能够高效的实现3D模型效果,毕竟是从0开始学习,感觉pano2vr这款软件挺容易上手,并且可以很容易实现简单的热点交互,可以根据交互需求设置皮肤,故将这一款软件推荐给大家: 1.简 ...

  6. 今日吐槽20151208.net服务器控件

    正文 今天有个小任务是给页面添加一个搜索条件,复选框多选.因为页面都是服务器控件,我也只能用服务器控件配合了.然后给页面加了一个  CheckBoxList  控件.后台通过数据表加载数据. fore ...

  7. 调试NodeJS应用

    OS:Windows 1.下载安装NodeJS 点击http://nodejs.org/界面上“Install”,下载后运行安装,默认安装到到C:\Program Files\nodejs.安装后确认 ...

  8. [转]LoadRunner脚本录制常见问题整理

    LoadRunner脚本录制常见问题整理 1.LoadRunner录制脚本时为什么不弹出IE浏览器? 当一台主机上安装多个浏览器时,LoadRunner录制脚本经常遇到不能打开浏览器的情况,可以用下面 ...

  9. mysql 远程连接 1045 Access denied for user 'root'@'XX.XX.XX.XX' (using password:YES)

    用户名/密码错误,需要输入开放远程时设置的密码

  10. 【BZOJ】1053: [HAOI2007]反素数ant

    1053: [HAOI2007]反素数ant Description: g(x)表示x的约数个数,反素数:对于任意的i (i < x),均有g(i) < g(x),则x为反素数:现在输入不 ...