游标

声明    不占内存

打开    申请内存    多行多列

获取    每次取一行,

关闭

隐式游标的属性:

SQL%ROWCOUNT    成功操作的行的数量

SQL%FOUND       发现复合条件的行返回TRUE

SQL%NOTFOUND    没有发现复合条件的行回TRUE

SQL%ISOPEN      游标打开状态(boolean)

练习 12:打印隐式游标属性

declare

v_count number;

begin

select count(*) into v_count from scott.emp;

dbms_output.put_line(chr(10)||'select return '||sql%rowcount||' rows!');

end;

begin

delete emp;

dbms_output.put_line(chr(10)||sql%rowcount||' rows deleted!');

--rollback;

end;

/

显式游标使用流程:

1.声明 declare

cursor c_name is subquery;

2.打开 open

3.获取 fetch

4.关闭 close

1.简单游标的使用

游标是在open时使用内存的.获取一次,内存中就少一行.

declare

cursor c1 is select ename,sal from scott.emp;

v_ename scott.emp.ename%type;

v_sal   scott.emp.sal%type;

begin

open c1 ;

loop

fetch c1 into v_ename,v_sal;

dbms_output.put_line(v_ename||' '||v_sal);

exit when c1%rowcount>5;

end loop;

close c1;

end;

/

declare

cursor c1

is

select employee_id,salary from employees;

v_id employees.employee_id%type;

v_sal employees.salary%type;

begin

open c1;

loop

if c1%notfound then

exit;

end if;

fetch c1 into v_id,v_sal;

dbms_output.put_line('Id is : '||v_id||'  '||'salary is : '||v_sal);

end loop;

close c1;

end;

2.使用游标取表中的所有行所有列

declare

cursor c1 is select * from scott.dept;

v_deptno dept.deptno%type;

v_dname  dept.dname%type;

v_loc  dept.loc%type;

begin

open c1;

loop

fetch c1 into v_deptno,v_dname,v_loc;

exit when C1%NOTFOUND;

dbms_output.put_line(v_deptno||' '||v_dname||' '||v_loc);

end loop;

close c1;

end;

/

3.游标for循环:使用for循环来代替loop循环

for循环中的变量根据in关键字后面的内容而决定变量的类型

如果in后面是数字 则变量是number类型标量变量

如果in后面是游标 则变量是record类型复合变量

declare

cursor c1 is select ename,sal from scott.emp;

begin

for r1 in c1 loop

exit when c1%rowcount>5;

dbms_output.put_line(r1.ename||' '||r1.sal);

end loop;

end;

/

4. 使用游标for循环 可以省略游标的声明

但这种游标for循环不能使用隐式游标属性控制 要自己添加计数器

declare

v_num number := 0;

begin

for r1 in (select ename,sal from scott.emp) loop

-- dbms_output.put_line(SQL%rowcount);

v_num := v_num + 1;

exit when v_num > 5;

dbms_output.put_line(r1.ename||' '||r1.sal);

end loop;

end;

/

set serveroutput on

declare

v_number NUMBER:=1;

begin

for r1 in (select * from hr.employees) loop

--     dbms_output.put_line(sql%rowcount);

if v_number > 5 then

exit;

end if;

dbms_output.put_line(r1.last_name);

v_number := v_number+1;

end loop;

end;

/

5. 参数游标

declare

cursor c1(v_deptno scott.emp.deptno%type)

is

select deptno,ename,sal from scott.emp where deptno=v_deptno;

begin

for r1 in c1 (&deptno) loop

dbms_output.put_line(r1.deptno||' '||r1.ename||' '||r1.sal);

end loop;

end;

/

declare

cursor c1(deptno hr.employees.department_id%type)

is

select last_name,department_id,salary from hr.employees where department_id=deptno;

begin

for emp_rec in c1(&did) loop

dbms_output.put_line('Name: '||emp_rec.last_name||' -- '||'Deptno: '||emp_rec.department_id||' -- '||

'Salary: '||emp_rec.salary);

end loop;

end;

/

练习 1: 基本loop循环+显式游标的使用

DECLARE

v_empno employees.employee_id%TYPE;

v_ename employees.last_name%TYPE;

CURSOR emp_cursor IS SELECT employee_id, last_name FROM employees; --声明

BEGIN

OPEN emp_cursor; --打开

LOOP

FETCH emp_cursor INTO v_empno, v_ename; --获取

exit when emp_cursor%rowcount>20;

DBMS_OUTPUT.PUT_LINE (TO_CHAR(v_empno)||' '|| v_ename);

END LOOP;

CLOSE emp_cursor; --关闭

END ;

/

练习 2: for循环+显式游标的使用

DECLARE

v_empno employees.employee_id%TYPE;

v_ename employees.last_name%TYPE;

CURSOR emp_cursor IS SELECT employee_id, last_name FROM employees;

BEGIN

OPEN emp_cursor;

FOR i IN 1..10 LOOP

FETCH emp_cursor INTO v_empno, v_ename;

DBMS_OUTPUT.PUT_LINE (TO_CHAR(v_empno)||' '|| v_ename);

END LOOP;

CLOSE emp_cursor;

END ;

/

游标for循环:

declare

cursor emp_cursor is select rownum,employee_id,last_name from employees; --声明

begin

for emp_record in emp_cursor loop --隐式打开隐式获取

exit when emp_cursor%rowcount>23;

dbms_output.put_line(emp_record.rownum||' '||

emp_record.employee_id||' '||

emp_record.last_name);

end loop; --隐式关闭

end;

/

省略游标定义:

begin

for r in (select last_name from employees) loop

dbms_output.put_line(r.last_name);

end loop;

end;

/

高级显式游标(带参数的游标):

练习 1:通过传入不同的参数使打开游标时取到不同的结果集

declare

cursor c1 (p_deptno number,p_job varchar2)

is

select empno,ename

from emp

where deptno=p_deptno

and job=p_job;

begin

Dbms_output.put_line('first fetch cursor!');

for r_c1 in c1(10,'MANAGER') loop --open cursor时传入不同的实际参数得到不同的游标上下文!

Dbms_output.put_line(r_c1.empno||' '||r_c1.ename);

end loop;

Dbms_output.put_line('second fetch cursor!');

for r_c1 in c1(20,'MANAGER') loop

Dbms_output.put_line(r_c1.empno||' '||r_c1.ename);

end loop;

Dbms_output.put_line('third fetch cursor!');

for r_c1 in c1(30,'MANAGER') loop

Dbms_output.put_line(r_c1.empno||' '||r_c1.ename);

end loop;

end;

/

练习:获取每个部门前两个雇员的信息

获取10部门前两个人的信息

declare

cursor c1 is select * from scott.emp

where deptno=10;

begin

for r1 in c1 loop

exit when c1%rowcount=3 or c1%notfound;

dbms_output.put_line(r1.ename||' '||r1.deptno);

end loop;

end;

/

使用替代变量取指定部门的前两个人的信息

declare

cursor c1 is select * from scott.emp

where deptno=&p_deptno;

begin

for r1 in c1 loop

exit when c1%rowcount=3 or c1%notfound;

dbms_output.put_line(r1.ename||' '||r1.deptno);

end loop;

end;

/

显示所有部门的工资最高的前两位员工的信息;

declare

cursor dept

is

select distinct department_id from employees order by department_id;

cursor emp(deptno number)

is

select employee_id,department_id,last_name,salary from employees

where department_id = deptno order by salary;

begin

for d in dept loop

for e in emp(d.department_id) loop

exit when emp%rowcount > 2 or emp%notfound;

dbms_output.put_line(e.employee_id||' : ' ||e.department_id ||' : '||e.last_name||' : ' || e.salary);

end loop;

end loop;

end;

/

使用高级游标代替替代变量

declare

cursor c1(p_deptno number) is select * from scott.emp

where deptno=p_deptno;

begin

for r1 in c1(10) loop

exit when c1%rowcount=3 or c1%notfound;

dbms_output.put_line(r1.ename||' '||r1.deptno);

end loop;

for r1 in c1(20) loop

exit when c1%rowcount=3 or c1%notfound;

dbms_output.put_line(r1.ename||' '||r1.deptno);

end loop;

for r1 in c1(30) loop

exit when c1%rowcount=3 or c1%notfound;

dbms_output.put_line(r1.ename||' '||r1.deptno);

end loop;

end;

/

使用循环嵌套简化上面的代码

declare

cursor c2 is select distinct deptno from scott.emp;

cursor c1(p_deptno number) is

select * from scott.emp

where deptno=p_deptno;

begin

for r2 in c2 loop

for r1 in c1(r2.deptno) loop

exit when c1%rowcount=3 or c1%notfound;

dbms_output.put_line(r1.ename||' '||r1.deptno);

end loop;

end loop;

end;

/

练习 2:将每个部门工资小于2000的职员工资涨10%

declare

cursor c1 is select deptno from scott.dept;

cursor c2 (p_deptno number,p_job varchar2)

is

select empno,ename,sal

from emp

where deptno=p_deptno

and job=p_job

for update of sal;

begin

for r_c1 in c1 loop

dbms_output.put_line('第'||c1%rowcount||'次获取游标c1' || '修改'||r_c1.deptno||'部门职员的工资');

for r_c2 in c2(r_c1.deptno,'CLERK') loop  /* 参数游标的好处的就是可以使锁定行更少 更有利于并发 */

if r_c2.sal<2000 then

update scott.emp set sal=sal*1.1

where current of c2;  /* 只修改C2游标所涉及到的行 */

end if;

end loop;

end loop;

end;

/

declare

cursor d1 is select distinct department_id from hr.e;

cursor e1(deptno hr.e.department_id%type)

is

select employee_id,salary from hr.e

where department_id=deptno;

begin

for d_info in d1 loop

for e_info in e1(d_info.department_id) loop

if e_info.salary

update hr.e set salary=salary*1.1 where employee_id=e_info.employee_id;

end if;

end loop;

end loop;

end;

动态游标:ref游标

强类型的动态游标

弱类型的动态游标

强类型的动态游标的样例:

declare

type emp_record_type is record(

empno employees.employee_id%type,

ename employees.last_name%type);

type emp_cursor is REF CURSOR return emp_record_type;

v_employee emp_record_type;

v_empno employees.salary%type := &no;

v_emp_cursor emp_cursor;

begin

if v_empno > 150 then

open v_emp_cursor for

select employee_id,last_name from employees

where employee_id > 150;

else

open v_emp_cursor for

select employee_id,last_name from employees

where employee_id <= 150;

end if;

fetch v_emp_cursor into v_employee;

while v_emp_cursor%found loop

dbms_output.put_line(v_employee.empno||' : '||v_employee.ename);

fetch v_emp_cursor into v_employee;

end loop;

close v_emp_cursor;

end;

弱类型的动态游标的样例:

declare

type emp_record_type is record(

empno number,

ename varchar2(100));

type emp_cursor is REF CURSOR;

v_employee emp_record_type;

v_no employees.salary%type := &no;

v_emp_cursor emp_cursor;

v_dname varchar2(50);

begin

if v_no > 150 then

open v_emp_cursor for

select employee_id,last_name from employees

where employee_id > 150;

else

open v_emp_cursor for

select department_name from departments

where department_id <= 150;

end if;

if v_no > 150 then

fetch v_emp_cursor into v_employee;

while v_emp_cursor%found loop

dbms_output.put_line(v_employee.empno||' : '||v_employee.ename);

fetch v_emp_cursor into v_employee;

end loop;

close v_emp_cursor;

else

fetch v_emp_cursor into v_dname;

while v_emp_cursor%found loop

dbms_output.put_line(v_dname);

fetch v_emp_cursor into v_dname;

end loop;

close v_emp_cursor;

end if;

end;

有定义游标结构(用return定义)的就是强类型 使用时必须按定义去取值 取值数量与定义匹配

弱类型没有定义游标结构 随SQL返回结果而构建游标的结构 特点是灵活 完全依赖于SQL 容易出错 SQL错游标就错

参照类型(ref cursor 程序间传递结果集)

create or replace package ref_package

as

TYPE emp_record_type IS RECORD

(ename VARCHAR2(25),

job VARCHAR2(10),

sal NUMBER(7,2));

TYPE weak_ref_cursor IS REF CURSOR;--弱类型,不规定返回值

TYPE strong_ref_cursor IS REF CURSOR return emp%rowtype;--强类型,规定返回值

TYPE strong_ref2_cursor IS REF CURSOR return emp_record_type;--强类型,规定返回值

end ref_package;

/

弱类型ref测试: 没有指定游标结构

create or replace procedure test_ref_weak

(p_deptno emp.deptno%type, p_cursor out ref_package.weak_ref_cursor)

is

begin

case p_deptno

when 10 then

open p_cursor for

select empno,ename,sal,deptno

from emp where deptno=p_deptno;

when 20 then

open p_cursor for

select *

from emp where deptno=p_deptno;

end case;

end;

/

var c refcursor

exec test_ref_weak(10,:c); --传入不同形式参数,走不同分支,返回不同结果集!

print c

exec test_ref_weak(20,:c);

print c

*oracle 9i 中定义了系统弱游标类型 sys_refcursor  可以和任何查询相关联

/* Oracle 9i */

create or replace procedure test_p

( p_deptno number, p_cursor out sys_refcursor)

is

begin

open p_cursor for

select *

from   emp

where  deptno = p_deptno;

end test_p;

/

create or replace function getemp

return sys_refcursor

as

emp_cursor sys_refcursor;

begin

open emp_cursor for select * from scott.emp;

return  emp_cursor;

end;

/

select getemp from dual;

强类型ref测试:查询结构必须符合游标返回值结构,否则报错:

PLS-00382: expression is of wrong type

create or replace procedure test_ref_strong

(p_deptno emp.deptno%type, p_cursor out ref_package.strong_ref_cursor)

is

begin

open p_cursor for

select *

from emp where deptno=p_deptno;

end test_ref_strong;

/

var c refcursor

exec test_ref_strong(10,:c);

create or replace procedure test_call

is

c_cursor ref_package.strong_ref_cursor;

r_emp  emp%rowtype;

begin

test_ref_strong(10,c_cursor);

loop

fetch c_cursor into r_emp;

exit when c_cursor%notfound;

dbms_output.put_line(r_emp.ename);

end loop;

close c_cursor;

end test_call;

/

exec test_call;

强类型ref测试:

create or replace procedure test_ref2_strong

(p_deptno emp.deptno%type, p_cursor out ref_package.strong_ref2_cursor)

is

begin

open p_cursor for

select ename,job,sal

from emp where deptno=p_deptno;

end test_ref2_strong;

/

var c refcursor

exec test_ref2_strong(10,:c);

oracle cusor游标,oracle 游标cursor相关推荐

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

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

  2. oracle游标等待,Oracle Mutex 等待事件之: cursor mutex X

    Oracle Mutex 等待事件之: cursor mutex X Cursor Mutex X 是当会话对某个 Cursor 请求排他模式锁,但是该Cursor 上已经有 S 或 X 模式的锁定, ...

  3. oracle 记录给游标,Oracle游标 CURSOR实例详解

    一.游标概述: 游标(cursor)是数据库系统在内存中开设的一个数据缓冲区,存放SQL语句的执行结果. 每个游标都有一个名字,用户可以用SQL语句逐一从游标中获取记录,并赋给变量做进一步处理. 作用 ...

  4. oracle显性游标,Oracle高级显式游标的使用

    1.参数化的游标作用:多次打开相同的游标,返回不同的结果集.游标声明部分的形参必须与OPEN语句中提供的实参相对应(数量与数据类型). 例1: DECLARE v_empno emp1.empno%T ...

  5. oracle存储过程详解--游标 实现增、删、改、查的

    注:以下是转来的内容,但是设计PLSQL代码,原文有问题,所以PLSQL代码我都验证修改了.测试需要在scott/tiger下进行,对于没有的表,需要自行创建,表复制的语句为 CREATE TABLE ...

  6. oracle中判断空,Oracle中判断空游标的方法

    1.声明包 create or replace package TAL_TEST is -- Author : ADMINISTRATOR -- Created : 2012/12/9 15:15:3 ...

  7. 13、oracle数据库下的游标

    ORACLE下的游标操作 游标是sql的一个内存工作区,由系统或者用户以变量的形式定义.游标的作用是用于临时存储从数据库中提取的数据块.游标有静态游标.动态游标之分,静态游标又可分为隐式游标和显式游标 ...

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

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

  9. oracle创建多个游标,Oracle——游标的创建和使用

    游标 SQL语言是面向集合的,是对指定列的操作.如果要对列中的指定行进行操作,就必须使用游标. 当在PL/SQL块中执行查询语句(SELECT) 和数据操纵语句(DML) 时,Oracle会为其分配一 ...

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

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

最新文章

  1. eclipse 工程复制
  2. directx 9.27.1734 多语言完整版 下载
  3. Express 结合 multer 上传图片
  4. 【OpenCV】OpenCV函数精讲之 -- argc 和argv参数
  5. 游族网络:中诚信国际将公司主体及游族转债列入信用评级观察名单
  6. kafka 消息顺序写入服务器
  7. Maven的安装与配置教程
  8. canvas实现简单画板
  9. java邮箱的表达式_Java邮箱正则表达式
  10. 北京机动车和自住房摇号查询
  11. windows 7可用软件搜索贴~(转)(申请置顶)
  12. android银行卡输入密码,android 仿微信添加银行卡时输入支付密码
  13. pandas(四)pandas的拼接操作
  14. 微信小程序开发什么工具好?
  15. 给俺的 CSDN 博客加背景音乐 - 高大尚的《心经》背景音乐
  16. DLNA(媒体共享)、Airplay(IOS系统的镜像以及共享)、Miracast(屏幕镜像)
  17. 实施ASP.NET Core应用程序的常见陷阱
  18. Android FFmpegMediaMetadataRetriever获取歌曲的作者
  19. 记账之后的收支明细,如何以收支图表的形式呈现
  20. linux系统忘记登录密码怎么办

热门文章

  1. DevExpress chartControl 基本结构说明
  2. 美的硅谷研发中心成立,专注人工智能推动产品智能化升级
  3. 基于Java的学生请销假审批管理系统的设计与实现毕业设计源码130939
  4. pc版最终幻想测试软件,先来跑个分:《最终幻想15》PC版跑分软件发布
  5. html按钮轮播图,四种方式实现轮播图
  6. 实现用java做一个简易版《羊了个羊》小游戏(附源代码)
  7. 15.笔记go语言——Web编程概念
  8. 安卓学习第14课——GridView(简单图片浏览器1)
  9. CODESYS在智能装备中的应用案例——机器人的“眼睛”
  10. React项目中应用TypeScript