Oracle principle: cursor, display cursor, implicit cursor, reference cursor

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:

Guess you like

Origin blog.csdn.net/superSmart_Dong/article/details/107027864