1.游标是一种访问机制,它允许用户访问单独的数据行(对数据逐行进行操作),而非对整个结果行集进行操作.
--使用游标的步骤:
--a.创建游标 cursor 游标名 is select 表.字段 from 表名 [for update]; //如果使用游标对表进行操作时,需要加上for update
--b.打开游标 open 游标名;
--c.存取游标 fetch 游标名 into 变量; //将游标读到的值存放在变量中
--d.关闭游标 close 游标名;
--游标的属性(同样也有
%ROWCOUNT 记录修改的条数
%NOTFOUND FOUND的否定
%ISOPEN 判断游标是否打开
%FOUND 判断游标是否指向一条记录
2.游标显示所有的员工姓名
//打开显示不然看不到输出
set serveroutput on;
//创建了一个存储过程
create or replace procedure showEmpEname as
cursor emp_cur is select ename from emp; //声明游标
v_name emp.ename%type;
begin
open emp_cur; //打开游标
fetch emp_cur into v_name; //使用游标操作数据
while emp_cur%FOUND loop
dbms_output.put_line('Ename='||v_name);
fetch emp_cur into v_name;
end loop;
close emp_cur; //关闭游标
end;
//使用 EXEC 存储过程名字; 来执行存储过程
SQL> exec showEmpEname;
Ename=SMITH
Ename=ALLEN
Ename=WARD
Ename=JONES
Ename=MARTIN
Ename=BLAKE
Ename=CLARK
Ename=SCOTT
Ename=KING
Ename=TURNER
Ename=ADAMS
Ename=JAMES
Ename=FORD
Ename=MILLER
PL/SQL 过程已成功完成。
2-使用 fetch bulk collect into 批量提取数据
declare
cursor emp_cur is select ename from emp;
type emp_name_type is table of emp.ename%type;//定义一个相当于数组的类型
emp_name emp_name_type;
begin
open emp_cur;
fetch emp_cur bulk collect into emp_name;
for i in 1..emp_name.count loop
dbms_output.put_line('name: ' || emp_name(i));
end loop;
close emp_cur;
end;
3--用游标方式显示姓名和工资
declare
cursor emp_cur is select ename,sal from emp;
v_name emp.ename%type;
v_sal emp.sal%type;
begin
open emp_cur;
loop
fetch emp_cur into v_name,v_sal;
exit when emp_cur%NOTFOUND;
dbms_output.put_line('name='||v_name||'sal='||v_sal);
end loop;
close emp_cur;
end;
4-用游标方式显示姓名和工资(批量提取)
declare
cursor emp_cur is select ename,sal from emp;
type emp_record_type is record(name emp.ename%type,sal emp.sal%type);//定义一个二维数组
type emp_table_type is table of emp_record_type;
emp_table emp_table_type;
begin
open emp_cur;
fetch emp_cur bulk collect into emp_table;
for i in 1..emp_table.count loop
dbms_output.put_line('emp'||emp_table(i).name||'sal'||emp_table(i).sal);
end loop;
close emp_cur;
end;
5 --使用基于游标定义的记录变量
--用游标方式显示姓名和工资(批量提取)
declare
cursor emp_cur is select ename,sal from emp;
type emp_table_type is table of emp_cur%rowtype;
emp_table emp_table_type;
begin
open emp_cur;
fetch emp_cur bulk collect into emp_table;
for i in 1..emp_table.count loop
dbms_output.put_line('name='||emp_table(i).ename||'sal='||emp_table(i).sal);
end loop;
close emp_cur;
end;
6--通过游标修改数据
1.声明时要加for update
2.更改数据时要加where current of cursor_name 意思是当游标指向当前一条的记录
create or replace procedure updateSalByDeptno(dno emp.deptno%type,addSal emp.sal%type)
is
cursor emp_cur is select sal from emp where deptno=dno for update;
v_sal emp.sal%type;
begin
open emp_cur;
loop
fetch emp_cur into v_sal;
exit when emp_cur%NOTFOUND;
if(v_sal<4000) then
update emp set sal=v_sal+addSal where current of emp_cur;
end if;
end loop;
close emp_cur;
end;
7.--删除数据
--删除某个部门的工资低于1000的员工
create or replace procedure deleteSalByDeptno(dno emp.deptno%type) is
cursor emp_cur is select sal from emp where deptno=dno for update;
v_sal emp.sal%type;
begin
open emp_cur;
loop
fetch emp_cur into v_sal;
exit when emp_cur%NOTFOUND;
if(v_sal<2000) then
delete from emp where current of emp_cur;
end if;
end loop;
close emp_cur;
end;
8.--游标循环
使用这个的好处是: 游标自动打开,且不用声明变量,end loop结束后自动关闭游标.
declare
cursor emp_cur is select ename,sal from emp;
begin
for emp_record in emp_cur loop
dbms_output.put_line('name='||emp_record.ename||'sal='||emp_record.sal);
end loop;
end;
更简洁的写法: 用一个select语句代替了游标
begin
for emp_record in (select ename,sal from emp) loop
dbms_output.put_line('Name: ' || emp_record.ename || ' Sal: ' || emp_record.sal);
end loop;
end;