游标

游标:(指针)
在Oracle中,游标是一种机制,是通过关键字 cursor 的来定义一组oracle查询出来的数据集,
可以把查询的数据集存储在内存当中,然后通过游标指向其中一条记录,通过循环游标达到循环数据集的目的。
我们可以通过该机制将名称分配给SELECT语句并处理该SQL语句中的信息。
select * from emp;

游标的分类
一. 静态游标–显式游标和隐式游标称为静态游标,因为在使用他们之前,游标的定义已经完成,不能再更改。
1.隐式游标:系统自动生成和管理的游标,又叫sql游标。DML语句和单行 select…into…语句会使用隐式游标。
2.显示游标:用户自己声明和管理的游标,即指定结果集。当查询返回结果超过一行时,就需要一个显式游标。

二. 动态游标(ref游标)–游标在声明时没有设定,在打开时可以对其进行修改。

游标属性:
cursor_name%found 布尔型属性,当最近一次提取游标操作 fetch 成功则为 true,否则为 false
cursor_name%notfound 布尔型属性,与%found 相反;
cursor_name%isopen 布尔型属性,当游标已打开时返回 true
cursor_name%rowcount 数字型属性,返回已从游标中读取的记录数。


隐式游标–系统自动生成和管理的游标,游标属性名均为sql 例如:sql%found
–一次只能处理一条数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
declare
v_emp emp%rowtype;
begin
select * into v_emp from emp where ename = 'SMITH';
if sql%found then dbms_output.put_line('有数据');
end if;
end;

declare
v_emp emp%rowtype;
begin
select * into v_emp from emp where ename = 'XIAOHONG';---从这一步开始报错,没机会走游标
if sql%found then dbms_output.put_line('有数据');
else dbms_output.put_line('无数据');
end if;
end;

declare
v_emp emp%rowtype;
begin
select * into v_emp from emp where ename = 'SMITH';
if sql%found then dbms_output.put_line(sql%rowcount);
end if;
end;



begin
delete from empa;
dbms_output.put_line(sql%rowcount);
end;

select * from empa;

显示游标–用户可以自己声明跟管理的游标,需要自己起名字

1.声明游标 cursor_name is select 语句–游标名后面可以直接跟参数,作用就是传递参数
2.打开游标 open cursor_name–游标名
3.传递参数 fetch cursor_name–游标名
4.关闭游标 close cursor_name–游标名

例:定义一个游标,打印出emp表中所有的员工姓名与薪资

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
declare
cursor cursor_emp is select * from emp;
v_emp emp%rowtype;
begin
open cursor_emp;
fetch cursor_emp into v_emp;---直接使用的时候只能获取第一条,想要获取多条需要放在循环中
close cursor_emp;
dbms_output.put_line(v_emp.ename||' '||v_emp.sal);
end;

declare
cursor cursor_emp is select * from emp;
v_emp emp%rowtype;
begin
open cursor_emp;
loop
fetch cursor_emp into v_emp; ---直接使用的时候只能获取第一条,想要获取多条需要放在循环中
exit when cursor_emp%notfound;
dbms_output.put_line(v_emp.ename || ' ' || v_emp.sal);
end loop;
close cursor_emp;
end;

declare
cursor cursor_emp is select * from emp where deptno = 10;
v_emp emp%rowtype;
begin
open cursor_emp;
loop
fetch cursor_emp into v_emp; ---直接使用的时候只能获取第一条,想要获取多条需要放在循环中
exit when cursor_emp%notfound;
dbms_output.put_line(v_emp.ename || ' ' || v_emp.sal);
end loop;
close cursor_emp;
end;

传递参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
declare
cursor cursor_emp(bm number) is select * from emp where deptno = bm;
v_emp emp%rowtype;
begin
open cursor_emp(&部门编号);
loop
fetch cursor_emp into v_emp;
exit when cursor_emp%notfound;
dbms_output.put_line(v_emp.ename || ' ' || v_emp.sal);
end loop;
close cursor_emp;
end;

declare
cursor cursor_emp(bm number) is select * from emp where deptno = bm;
--游标名中,需要传递的数据类型名需要自己命,不能跟字段名一样
--游标中需要传递的数据类型要保持一致
v_emp emp%rowtype;
begin
open cursor_emp(10);
loop
fetch cursor_emp into v_emp;
exit when cursor_emp%notfound;
dbms_output.put_line(v_emp.ename || ' ' || v_emp.sal);
end loop;
close cursor_emp;
end;

传递多个参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
declare
cursor cursor_emp(bm number,xm varchar2) is select * from emp where deptno = bm and ename = xm;
--游标名中,需要传递的数据类型名需要自己命,不能跟字段名一样
--游标中需要传递的数据类型要保持一致
v_emp emp%rowtype;
begin
open cursor_emp(20,'SMITH');
loop
fetch cursor_emp into v_emp;
exit when cursor_emp%notfound;
dbms_output.put_line(v_emp.ename || ' ' || v_emp.sal);
end loop;
close cursor_emp;
end;


declare
cursor cursor_emp(bm1 number,bm2 number) is select * from emp where deptno = bm1 or deptno = bm2;
v_emp emp%rowtype;
begin
open cursor_emp(20,10);--即使传递同字段同类型的参数,每个参数也需要对应属于自己的数据类型
loop
fetch cursor_emp into v_emp;
exit when cursor_emp%notfound;
dbms_output.put_line(v_emp.ename || ' ' || v_emp.sal);
end loop;
close cursor_emp;
end;

declare
cursor cursor_emp(bm number) is select * from emp where deptno = bm;
--游标名中,需要传递的数据类型名需要自己命,不能跟字段名一样
--游标中需要传递的数据类型要保持一致
v_emp emp%rowtype;
begin
open cursor_emp(in(10,20));--报错,不能使用集合一次传递多个参数
loop
fetch cursor_emp into v_emp;
exit when cursor_emp%notfound;
dbms_output.put_line(v_emp.ename || ' ' || v_emp.sal);
end loop;
close cursor_emp;
end;

在for循环中使用游标

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
declare
cursor cursor_emp is select * from emp;
v_emp emp%rowtype;
begin
for v_emp in cursor_emp loop
dbms_output.put_line(v_emp.ename || ' ' || v_emp.sal);
end loop;
end;

declare
cursor cursor_emp(bm number) is select * from emp where deptno = bm;
v_emp emp%rowtype;
begin
for v_emp in cursor_emp(&部门编号)loop
dbms_output.put_line(v_emp.ename || ' ' || v_emp.sal);
end loop;
end;

for循环在使用游标时,会自动进行打开,传递,关闭游标的过程
open fetch close

1.当进入循环时,游标 for 循环语句自动打开游标并提取第一行游标数据;
2.当程序处理完当前所提取的数据而进入下一次循环时,游标for循环语句自动提取下一行数据供程序处理;
3.当提取完 结果集中全部数据后,结束循环,并自动关闭循环;