游标是一个内存工作区,将数据库中读取的东西放入缓存中,不需要反复读取数据库。
我的emp表
1、显示游标 用户自己定义一个显示游标,通过与游标有关的语句进行处理,返回结果为多行多列的select语句。
显示游标分为4个部分:
1、声明游标 DECLEAR部分
2、打卡游标 BEGIN 定义部分
3、提取游标 FETCH 游标名 INTO 变量名
4、关闭游标 CLOSE
declare --定义部分,创建变量常量游标以及异常等
avg_sal number(7,2);
begin --执行部分,sql流程控制语句
select avg(t.薪水) into avg_sal from VIEW_2 t;
--select * into avg_sal from EMP2 t;没有数据报错
dbms_output.put_line('Oracle Hello World!');
dbms_output.put_line('程序员的平均工资为:'||avg_sal);
exception --例外处理部分——处理运行的各种错误
WHEN NO_DATA_FOUND Then
dbms_output.put_line('未查找到任何行!');
End;
FOR I IN 1..3 LOOP
//定义一个循环下面还可以引用I
END LOOP;
如果我想实现,将学生成绩表中分类,用游标统计选修表SC中分数段在0~59、60~79、80~89、90~100各个区间中人数及人名。那我应该怎么做呢?
DECLARE
CURSOR emp_cursor IS
SELECT SNO,sname FROM cs where grade>=90;
BEGIN
DBMS_OUTPUT.PUT_LINE('上了90分的人有:');
FOR CS_record IN emp_cursor LOOP
DBMS_OUTPUT.PUT_LINE(CS_record.SNO|| CS_record.Sname);
END LOOP;
END;
这里是将分数大于90的人取出放入缓冲区内,***——record是隐含定义的记录变量,即内置函数。
若要达到上面的效果,则是要将所有数据取到缓冲区内然后进行筛选分类输出。
DECLARE
CURSOR emp_cursor IS
SELECT SNO,SNAME,GRADE FROM cs;
BEGIN
FOR CS_record IN emp_cursor LOOP
IF CS_RECORD.GRADE>=90 THEN
DBMS_OUTPUT.PUT_LINE('90分以上的人'||CS_record.SNO|| CS_record.Sname);
ELSIF CS_RECORD.GRADE>=80 AND CS_RECORD.GRADE<90 THEN
DBMS_OUTPUT.PUT_LINE('80-90的人'||CS_record.SNO|| CS_record.Sname);
ELSIF CS_RECORD.GRADE>=70 AND CS_RECORD.GRADE<80 THEN
DBMS_OUTPUT.PUT_LINE('70-80的人'||CS_record.SNO|| CS_record.Sname);
ELSIF CS_RECORD.GRADE>=60 AND CS_RECORD.GRADE<70 THEN
DBMS_OUTPUT.PUT_LINE('60-70的人'||CS_record.SNO|| CS_record.Sname);
ELSE DBMS_OUTPUT.PUT_LINE('60分以下的人'||CS_record.SNO|| CS_record.Sname);
END IF;
END LOOP;
END;
2、隐式游标 一次只能读取一行数据,如select 系统自动完成
如DML操作,和单行select语句,隐式游标可以通过游标的属性来了解当前操作的结果。访问:通过名字sql来访问,每次只能访问前面的一个操作游标属性。
SQL%ROWCOUNT 返回成功执行的数据行数
SQL%FOUND 操作是否成功
SQL%NOTFOUND 与上面的相反
SQL%ISOPEN 判断sql语句是否结束,正在执行为true,结束为false
BEGIN
UPDATE emp SET sage=sage+100 WHERE e#=1234;
IF SQL%FOUND THEN --隐式游标可以通过游标的属性来了解当前操作的结果。
DBMS_OUTPUT.PUT_LINE('成功修改雇员工资!');
COMMIT;
ELSE
DBMS_OUTPUT.PUT_LINE('修改雇员工资失败!');
END IF;
END;
子程序