前提

我有这么一张残念的表。我屮艸芔茻,截屏的时候把鼠标截进来了。
残念的表

游标

类似于c的指针,c++中vector的迭代器(iterator)。类似于for语句中的i。

  • %found 影响一行以上为true,否则为false
  • %notfound 与第一条值相反
  • %isopen 是否打开
  • %rowcount 返回受影响的行数

隐式游标

样例1

1
2
3
4
5
6
7
8
9
10
11
12
13
set serveroutput on
declare
course_row course%rowtype;
begin
select * into course_row
from course where cid=3;
if sql%notfound then
dbms_output.put_line('没有记录');
else
dbms_output.put_line('有'||sql%rowcount||'条记录');
end if;
end;
/

样例2

与for语句搭配

1
2
3
4
5
6
7
8
9
10
11
set serveroutput on
declare
course_row course%rowtype;
begin
for course_row in (select * from course)
loop
dbms_output.put('课程名:'||course_row.cname);
dbms_output.put_line(' 课程编号:'||course_row.cid);
end loop;
end;
/

for&cursor

问题

为什么不行?

1
2
3
4
5
6
7
8
9
10
11
12
13
set serveroutput on
declare
type course_table is table of course%rowtype;
course_row course_table;
begin
select * into course_row from course;
if sql%notfound then
dbms_output.put_line('没有记录');
else
dbms_output.put_line('有'||sql%rowcount||'条记录');
end if;
end;
/

显示游标

声明语法

1
2
CURSOR cursor_name [(parameter[,parameter]...)]
[return return_type] IS select_statement;

打开和关闭

1
2
open cursor_name;
close cursor_name;

样例

fetch语句自动会返回下一个游标的地址。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
set serveroutput on
declare
CURSOR course_cursor(ID in number default 1)
is select * from course where cid>=ID;
course_row course%rowtype;
begin
open course_cursor(3);
loop
fetch course_cursor into course_row;
exit when course_cursor%notfound;
dbms_output.put('课程名:'||course_row.cname);
dbms_output.put_line(' 课程编号:'||course_row.cid);
end loop;
close course_cursor;
end;
/

for&cursor

与for语句搭配自动开关游标,不需要主动声明。

1
2
3
4
5
6
7
8
9
10
11
12
set serveroutput on
declare
CURSOR course_cursor
is select * from course;
begin
for r in course_cursor
loop
dbms_output.put('课程名:'||r.cname);
dbms_output.put_line(' 课程编号:'||r.cid);
end loop;
end;
/