There are three types of Oracle cursors: display cursors, implicit cursors, and reference cursors.
fetch...bulk collect into
The select statement returns all the result set to the user, and cannot perform a separate operation on each row of data in the result set. So the cursor can solve this problem.
The implicit cursor is automatically created by Oracle when the DML SQL statement is executed, and the name is fixed as sql
The display cursor is created by the user
REF cursor: REF cursor is used to process the results of dynamic SQL queries that can be determined at runtime
One, implicit cursor
The attributes contained in the implicit cursor are:
%FOUND: True when the SQL statement affects one or more rows
%NOTFOUND: True when the SQL statement does not affect any rows
%ROWCOUNT: The number of rows affected by the SQL statement
%ISOPEN: Whether the cursor is open
New table:
declare
sql_command varchar2(500);
isExsit number ;
begin
select count(1) into isExsit from user_tables where table_name ='SALARY_TBL';
if isExsit <> 0 then
sql_command :='truncate table salary_tbl';
execute immediate sql_command;
sql_command :='drop table salary_tbl';
execute immediate sql_command;
end if;
sql_command := '
create table salary_tbl(
employer_nm varchar(20) ,
department varchar(20) not null,
salary number not null,
leader_nm varchar(20)
)';
execute immediate sql_command;
for i in 1..13000
loop
insert into salary_tbl values('雇佣者'||i,'部门'||Mod(i,50),100+sqrt(i),'雇佣者'||Mod(i,20));
if Mod(i,1000)=0 then
commit;
end if;
end loop;
commit;
end;
/
--隐式游标示例
begin
update salary_tbl set DEPARTMENT ='部门3' where DEPARTMENT ='部门3';
if sql%found then
dbms_output.put_line('修改了'||sql%ROWCOUNT||'行');
end if;
rollback;
end;
/
Two, display the cursor
First, you need to define the cursor, and then open the cursor, then the cursor points to a certain result set. At this time, read line by line, and then close the cursor after reading.
cursor curname ( parameter set) is SQLstatement ;
----把领导者的薪资变成99999----
declare
sal salary_tbl.employer_nm%type;
cursor mycur is select distinct LEADER_NM from salary_tbl ;
begin
open mycur;
fetch mycur into sal;
while mycur%found loop
update salary_tbl set salary=99999 where employer_nm = sal;
fetch mycur into sal;
end loop;
close mycur;
end;
/
Example of display cursor for passing parameters:
----把除了部门9的领导者的薪资变成8888----
declare
sal salary_tbl.employer_nm%type;
cursor mycur(depnum number) is select distinct LEADER_NM from salary_tbl where
employer_nm in (select distinct LEADER_NM from salary_tbl)and department <>'部门'||depnum;
begin
open mycur(9);
fetch mycur into sal;
while mycur%found loop
update salary_tbl set salary=8888 where employer_nm = sal;
fetch mycur into sal;
end loop;
close mycur;
end;
/
The above is to use the cursor to query, the cursor can also be used to update and delete operations.
cursor curname ( parameter set) is SQLstatement for update ;
current of curname
----把除了部门8的领导者薪资变成7777----
declare
sal salary_tbl%rowtype;
cursor mycur(depnum number) is select * from salary_tbl where
employer_nm in (select distinct LEADER_NM from salary_tbl)and department <>'部门'||depnum for update;
begin
open mycur(8);
fetch mycur into sal;
while mycur%found loop
update salary_tbl set salary=7777 where current of mycur;
fetch mycur into sal;
end loop;
close mycur;
end;
/
The loop cursor can only be used for queries but greatly simplifies the code:
----把除了部门7的领导者薪资变成6666----
declare
sal salary_tbl%rowtype;
cursor mycur(depnum number) is select * from salary_tbl where
employer_nm in (select distinct LEADER_NM from salary_tbl)and department <>'部门'||depnum for update;
begin
for c1 in mycur(7) loop
update salary_tbl set salary=6666 where current of mycur;
end loop;
end;
/
Exercise: Use the cursor to initialize the table, create a new department table (department number, total employee salary, leadership)
declare
sql_command varchar2(500);
isExsit number ;
cursor dep_cur is select department,sum(salary) as allsalary from salary_tbl group by department;
depdata dep_cur%rowtype;
begin
select count(1) into isExsit from user_tables where table_name ='DEPARTMENT_TBL';
if isExsit <> 0 then
sql_command :='truncate table DEPARTMENT_TBL';
execute immediate sql_command;
sql_command :='drop table DEPARTMENT_TBL';
execute immediate sql_command;
end if;
sql_command := '
create table DEPARTMENT_TBL(
department varchar(20) not null,
all_salary number not null,
leaders varchar(100)
)';
execute immediate sql_command;
open dep_cur;
fetch dep_cur into depdata;
while dep_cur%found loop
insert into DEPARTMENT_TBL(department,all_salary) values(depdata.department,depdata.allsalary);
fetch dep_cur into depdata;
commit;
end loop;
close dep_cur;
end;
/
Three, refer to the cursor
The reference cursor can be used when the definition of the cursor cannot be determined directly;
定义:TYPE typename IS REF CURSOR;
typename refcursorname;
Assignment: OPEN refcursorname FOR sqlstatement;
For example: initialize DEPARTMENT_TBL.leaders to get all the leaders under the department.;
---初始化部门中的leader----
declare
cursor cur is select distinct department from salary_tbl ; --所有的部门
leadernm DEPARTMENT_TBL.LEADERS%type; --某个部门下的所有领导者,待赋值
type refcursor is ref cursor;
refcur refcursor; --参照游标
refdata salary_tbl.leader_nm%type; --某个部门下的某个领导者,待赋值
begin
for curdata in cur loop
--遍历部门集cur,确定部门curdata下的所有领导者集合
open refcur for select distinct leader_nm from salary_tbl where department=curdata.department;
leadernm :='';
fetch refcur into refdata;
while refcur%found loop
--遍历领导者集合,字符串拼接
if leadernm is null then
leadernm := leadernm ||refdata;
else
leadernm := leadernm ||','||refdata;
end if;
fetch refcur into refdata;
end loop; ---/refcur
dbms_output.put_line(curdata.department || ' '||leadernm);
update DEPARTMENT_TBL set LEADERS=leadernm where department=curdata.department;
end loop; --/cur
--commit;
close refcur;
end;
/
The result of the new table is as follows: