目录
[二重循环 三种循环随便嵌套](#二重循环 三种循环随便嵌套)
[exit continue return](#exit continue return)
[current of 语句](#current of 语句)
PLSQL基础语法(三)
二重循环 三种循环随便嵌套
begin
for n in 1..10
loop
dbms_output.put_line(n);
for j in 1..5
loop
dbms_output.put('*');
end loop;
dbms_output.put_line(null);
end loop;
end ;
exit continue return
1.EXIT:只能用于循环中,并且只是退出本次循环,继续执行下一条外层循环数据
2.RETURN:可以用于循环和非循环中:退出整个BEGIN...END,且不往下执行
3.CONTINUE:退出本次循环,直接进入下一次循环
--一重循环
begin
for i in 1 .. 10
loop
if i=1 then
continue;
end if;
if i=8 then
dbms_output.put('发财咯');
exit;
end if;
dbms_output.put_line(i);
end loop;
dbms_output.put_line('');
end;
--二重循环
begin
for i in 1 .. 5
loop
if i=3 then continue;
end if;
if i=4 then exit;
end if;
dbms_output.put_line(i);
for j in 1..5
loop
if j=3 then
continue;
end if;
if j=4 then
--exit;
return;
end if;
dbms_output.put_line(j);
end loop;
end loop;
end;
作业
sql
--1、99乘法表
declare
a number(10);
b number(10);
begin
for a in 1 .. 9
loop
for b in 1 .. a
loop
dbms_output.put(b||'*'||a||'='||(a*b)||' ');
end loop;
dbms_output.put_line(null);
end loop;
end;
--2、拼接一个直角三角形
begin
for i in 1 .. 9
loop
for j in 1 .. 2*i-1
loop
dbms_output.put('*');
end loop;
dbms_output.put_line(null);
end loop;
end;
--3、上个练习基础上拼接一个等腰三角形
begin
for i in 1 .. 9
loop
for j in 1 .. (8+i)
loop
if j between 9-i+1 and 9+i-1
then
dbms_output.put('*');
else
dbms_output.put(' ');
end if;
end loop;
dbms_output.put_line(null);
end loop;
end;
--4、上个练习基础上拼接一个菱形
begin
for i in 1 .. 9
loop
for j in 1 .. (8+i)
loop
if j between 9-i+1 and 9+i-1
then
dbms_output.put('*');
else
dbms_output.put(' ');
end if;
end loop;
dbms_output.put_line(null);
end loop;
for k in 1 .. 8
loop
for m in 1 .. 17-k
loop
if m between 1+k and 17-k
then
dbms_output.put('*');
else
dbms_output.put(' ');
end if;
end loop;
dbms_output.put_line(null);
end loop;
end;
/*5、打印输出100至200之间的全部素数,输出素数并统计共有多少个素数。
注:质数(prime number)又称素数,有无限个。一个大于1的自然数,除了1和它本身
外,不能被其他自然数整除,换句话说就是该数除了1和它本身以外不再有其他的因数;
否则称为合数。*/
declare
PrimeCount number(10):=0;
begin
for i in 100 .. 200
loop
for j in 2 .. floor(i/2)
loop
if mod(i,j)=0
then exit;
end if;
if j=floor(i/2)
then
dbms_output.put_line(i);
PrimeCount:=PrimeCount+1;
end if;
end loop;
end loop;
dbms_output.put_line('共有'||PrimeCount||'个素数');
end;
数据提取
游标
游标是一种从表中检索数据并进行操作的灵活手段,游标主要用在服务器上,处理由客户端发送给服务端的sql语句,或是批处理、存储过程、触发器中的数据处理请求。游标的优点在于它可以定位到结果集中的某一行,并可以对该行数据执行特定操作。作为一个备用方式,当我们穷尽了while循环,子查询,临时表,表变量,自建函数或其他方式仍然无法实现某些查询的时候用游标来实现。
隐式游标
通过一个简单直接的select...into 语句提取一行数据,并放在一个局部变量中。
显示游标
在声明单元declare中明确的声明一个查询。这样我们就可以在一个或者多个程序中打开游标并从中提取数据,可以得到隐式游标所没有的空值颗粒。
动态游标
使用游标变量(用ref cursor 类型声明),我们可以把指向一个查询结果集的指针从一个程序传递到另一个程序,从而提供了另一层灵活性。任何程序只需要访问这个变量,就可以打开游标提取数据.
游标使用流程
声明游标
cursor 游标名称 is sql语句;
打开游标
open 游标名称;
提取数据
fetch 游标名称 into 记录名;
关闭游标
close 游标名称;
--提取dept部门编号和部门名称
declare
cursor cur_dept is select * from dept;
v_dept cur_dept%rowtype;
begin
open cur_dept;
fetch cur_dept into v_dept;
dbms_output.put_line(v_dept.deptno||v_dept.dname);
fetch cur_dept into v_dept;
dbms_output.put_line(v_dept.deptno||v_dept.dname);
fetch cur_dept into v_dept;
dbms_output.put_line(v_dept.deptno||v_dept.dname);
fetch cur_dept into v_dept;
dbms_output.put_line(v_dept.deptno||v_dept.dname);
close cur_dept;
end;
游标属性
游标配合循环使用示例
declare
cursor cur_dept is select * from dept; --声明游标
v_dept cur_dept%rowtype; --声明游标变量
begin
open cur_dept; --打开游标
if cur_dept%isopen then
loop --开始循环
fetch cur_dept into v_dept; --抓取
exit when cur_dept%notfound; --循环边界
dbms_output.put_line(cur_dept%rowcount||'--'||v_dept.deptno||v_dept.dname); --打印
end loop;
close cur_dept; --关闭游标
end if;
end;
--while循环
declare
cursor cur_dept is select * from dept; --声明游标
v_dept cur_dept%rowtype; --声明游标变量
begin
open cur_dept; --打开游标
fetch cur_dept into v_dept; --抓取
while cur_dept%found
loop --开始循环
dbms_output.put_line(v_dept.deptno||v_dept.dname); --打印
fetch cur_dept into v_dept;
end loop;
close cur_dept; --关闭游标
end;
--for 会自动打开关闭游标
declare
cursor cur_dept is select * from dept ; --声明游标
begin
for v_dept in cur_dept
loop --开始循环
dbms_output.put_line(cur_dept%rowcount||'--'||v_dept.deptno||v_dept.dname); --打印
end loop;
end;
作业2
sql
-1、提取emp表的姓名和工资,显示游标序号,使用两种循环完成游标遍历输出 while for
--方法一
declare
cursor enamesal is select * from emp;
v_emp emp%rowtype;
begin
open enamesal;
fetch enamesal into v_emp;
while enamesal%found
loop
dbms_output.put_line(v_emp.ename||' '||v_emp.sal||' '||enamesal%rowcount);
fetch enamesal into v_emp;
end loop;
close enamesal;
end;
--方法二(超好用)
declare
cursor enamesal is select * from emp;
begin
for i in enamesal
loop
dbms_output.put_line(i.ename||' '||i.sal||' '||enamesal%rowcount);
end loop;
end;
--2、上题基础上对员工表2-4条数据输出,for循环实现
declare
cursor enamesal is select * from emp;
begin
for i in enamesal
loop
if enamesal%rowcount between 2 and 4
then
dbms_output.put_line(i.ename||' '||i.sal||' '||enamesal%rowcount);
end if;
end loop;
end;
参数游标
cursor 游标名称(参数名称 in 参数数据类型 :=默认值 ) is sql语句
open 游标名称(参数)
只有open需要加参数,其他直接使用游标名称
--简单输入
declare
cursor cur_emp is select * from emp where deptno=&部门编号;
begin
for v_emp in cur_emp
loop
dbms_output.put_line(v_emp.ename);
end loop;
end;
--传入参数for循环
declare
cursor cur_emp(deptin number :=20) is select * from emp where deptno=deptin;
dno number(4);
begin
select max(deptno) into dno from emp;
for v_emp in cur_emp(dno)
loop
dbms_output.put_line(v_emp.ename||v_emp.deptno);
end loop;
end;
--传入参数while循环
declare
cursor cur_emp(deptin number :=20) is select * from emp where deptno=deptin;
v_emp cur_emp%rowtype;
dno number(4);
begin
select max(deptno) into dno from emp;
open cur_emp(dno);
fetch cur_emp into v_emp;
while cur_emp%found
loop
dbms_output.put_line(v_emp.ename||v_emp.deptno);
fetch cur_emp into v_emp;
end loop;
close cur_emp;
end;
--二重循环传入参数for循环
declare
cursor cur_dept is select * from dept ;
cursor cur_emp(deptin number) is select * from emp where deptno=deptin;
begin
for v_dept in cur_dept
loop
dbms_output.put_line(v_dept.deptno||'---'||v_dept.dname);
for v_emp in cur_emp(v_dept.deptno)
loop
dbms_output.put_line(' '||v_emp.ename||'-'||v_emp.job||'-'||v_emp.sal);
end loop;
end loop;
end;
--二重循环传入参数while循环
declare
cursor cur_dept is select * from dept ;
cursor cur_emp(deptin number) is select * from emp where deptno=deptin;
v_emp cur_emp%rowtype;
begin
for v_dept in cur_dept
loop
dbms_output.put_line(v_dept.deptno||'---'||v_dept.dname);
open cur_emp(v_dept.deptno);
fetch cur_emp into v_emp;
while cur_emp%found
loop
dbms_output.put_line(' '||v_emp.ename||'-'||v_emp.job||'-'||v_emp.sal);
fetch cur_emp into v_emp;
end loop;
close cur_emp;
end loop;
end;
current of 语句
通过where current of 语句进行数据更新或删除就可以直接修改最后取出的数据行,而不用再写判断条件了。该语法无法和returning 语句一起使用。
update 表名 set 列名=值 where current of 游标名;
示例
declare
cursor cur_emp is select * from emp where deptno='20' and sal<5000 for update;
begin
for v_emp in cur_emp
loop
--update emp set sal=8000 where deptno='20' and sal<5000;
update emp set sal=8000 where current of cur_emp;
end loop;
end;
作业3
sql
--1、寻找每个sc表中分数大于平均分数的考试的信息,显示学生编号,课程编号,分数
select sno,cno,score
from sc
where score>(
select avg(score) from sc
);
--2、使用游标获取每个老师所教授课程的课程名称以及平均成绩,二重循环实现
declare
cursor v_teacher is select tno,tname
from teacher;
cursor v_course(tt teacher.tno%type) is select cname,nvl2(avg(score),to_char(avg(score)),'没有成绩') avgsc
from course left join sc on course.cno=sc.cno where tno=tt
group by cname;
begin
for i in v_teacher
loop
dbms_output.put_line(i.tno||'--'||i.tname);
for j in v_course(i.tno)
loop
dbms_output.put_line(' '||j.cname||'---'||j.avgsc);
end loop;
end loop;
end;