- 显示游标
--显示游标的定义
declare
--定义一个显示游标,并确定内容是什么,cursor... is select....from....
cursor c_emp is select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp;
---定义一个行对象
r_emp emp%rowtype;
--这里定义的式行列式,所以就需要在定义游标的时候取出emp的所有字段,
--并且顺序还要按照emp的顺序来取
begin
--操作游标步骤
--打开游标
open c_emp;
--使用循环抓取游标中的所有数据
loop
--抓取数据放入变量或行对象中
fetch c_emp into r_emp;
--这里不需要from语句
---抓取数据的循环终止条件
exit when c_emp%notfound;
---取出行对象的每一个字段,抓取一条数据就打印出来
dbms_output.put_line('姓名:'||r_emp.ename||',员工编号:'||r_emp.empno);
end loop;
--关闭游标
close c_emp;
end;
- 输入部门编号,查询视图v_emp_dept表的部门名称和员工名称
我们通过一个例题来加深对显示游标的理解
这里我们先创建一个视图
create or replace view v_emp_dept as select emp.deptno,dname,ename from emp join dept on dept.deptno=emp.deptno;--->这里创建视图的时候我们添加一个or replace 可以多次执行该语句
那么这个视图我们就创建好了
下面我们就需要通过用户输入一个部门编号,然后我们返回出查询的结果
---利用游标查询,先将SQL语句查询的结果放在游标里面,再 利用循环将查询结果输出
declare
cursor c_emp_dept is
select ename,dname from v_emp_dept where deptno='&请输入部门编号:';
--->cursor 相当于存储了我们需要查询的所有信息,也就是我们将查询的SQL表放在了cursor里面,并且记得游标的声明是放在declare语句里面的
e_name v_emp_dept.ename%type;
d_name v_emp_dept.dname%type;
begin
open c_emp_dept;--->一旦定义了游标就要记得先把打开游标和关闭游标写好
--这里需要先取出一条数据再进入while循环
fetch c_emp_dept into e_name,d_name;
--while ....loop.....end loop ==while() do......
while c_emp_dept%found loop
--取出一条数据就打印出来,然后再继续取,直到c_emp_dept%nofound就跳出循环
dbms_output.put_line('当前的行数:'||c_emp_dept%rowcount||',员工名称:'||e_name||',部门名称:'||d_name);
fetch c_emp_dept into e_name,d_name;
end loop;
close c_emp_dept;
end;
----使用for循环遍历存储有查询结果的游标,并且输出
declare
cursor c_cursor is
select ename,dname from v_emp_dept where deptno='&请输入部门编号:';
begin
---使用for each 遍历游标的好处是不用再重新定义一个行对象或者字段对象来通过抓取游标中的字段进行存储
--这里的i就相当于一张表,和游标一模一样,可以直接通过i来获取表中的字段,并且也没有了while之类的循环的
--终止条件
for i in c_cursor loop
dbms_output.put_line('员工名称:'||i.ename||',部门名称:'||i.dname);
end loop;
end;
----遍历显示游标的循环有while循环和for循环,以后我们一般都采用for循环
–隐示游标
–隐示没有声明,打开,关闭操作,
–隐示游标是由系统自动产生,名字统一叫做SQL(每执行一个DML语句就会产生一个隐示游标)
–在隐示游标中可以使用三个属性
–%NOTFOUND
–%FOUND
–%ROWCOUNT写一个PL/SQL块,插入表employee中100条数据。插入该表中字段id用序列seq_employee实现,薪水和姓名字段可以任意填写。
--.写一个PL/SQL块,插入表employee中100条数据。
--插入该表中字段id用序列seq_employee实现,薪水和姓名字段可以任意填写。
create table t_employee (
e_id number primary key,
e_name varchar2(25),
e_sal number(7,2)
);
select * from t_employee;
--使用序列sequence之前必须要先创建一个序列
create sequence seq_employee;
--使用PL/SQL块循环插入数据
--注意这里使用的for循环和遍历游标的for循环不一样
--这里的for循环是for i in start..end loop....end loop
--这里的i就是一个迭代器的变量值
--而遍历表或者游标的时候for i in c_cursor loop...end loop;
--这里的i代指的就是一张表本身,或者游标本身
declare
begin
for i in 1..100 loop
insert into t_employee values(seq_employee.nextval,'wang'||i,i*500);
commit;---凡是不是查询的语句最好都要设置为自动提交,防止死锁
end loop;
end;
select * from t_employee;
那么我们可以看下插入数据之后的表
- –.写一个语句块,在语句块中定义一个显式游标,按id升序排列,打印表emp中前十条数据。
declare
--定义一个游标把查询语句返回出来的表存储起来
cursor c_mycur is
select e_id,e_name,e_sal from t_employee where rownum<=10 ;
begin
--接下来的任务就是将游标中的表利用循环打印出来
--这里我们利用for循环来遍历游标
for i in c_mycur loop
dbms_output.put_line('编号'||i.e_id||',姓名:'||i.e_name||',薪水:'||i.e_sal);
end loop;
end;
- 创建存储过程pro_emp,输入员工薪水范围,返回员工工号、姓名、薪水结果集,结果集按员工薪水升序排列。
--对于参数记得定义类型,这里是形参,不用定义长度,不然会报错
--定义存储过程和定义视图一样都可以加上or replace 以免重复执行该语句会报错
--创建存储过程同样需要PL/SQL语句块不过不需要声明的部分,只需要begin...end pro_xx;
--一定记得结束的时候要写存储过程的名字
--对于存储过程传递的形参,传入不需要写in,但是输出的参数需要再参数名和类型名之间添加out
--存储过程的定义
create or replace procedure pro_emp (min_sal number ,max_sal number , sal_result out sys_refcursor)is---->这里定义输出参数为一个引用型的游标
begin
open sal_result for select e_id,e_name,e_sal from t_employee
where e_sal between min_sal and max_sal;---->要向引用型的游标中添加数据需要先打开游标然后利用for 赋值给游标
end pro_emp;
--存储过程的调用
declare
sal_result sys_refcursor;--由于存储过程里面有引用型的变量,
--所以这里的实参也需要声明一个引用型的游标,引用型的游标声明的时候直接定义类型就行了
--不用像显示游标采用cursor c_cursor is select from
e_row t_employee%rowtype;---不能用for each 就只能通过行对象来存储游标取出来的字段
begin
pro_emp(2000,5000,sal_result);
--for i in sal_result loop
--使用引用游标的时候就不能使用for each进行遍历了
loop
fetch sal_result into e_row;
exit when sal_result%notfound;
dbms_output.put_line('编号:'||e_row.e_id||',姓名:'||e_row.e_name||',工资:'||e_row.e_sal);
end loop;
end;