Oracle 原理:游标,显示游标、隐式游标、参照游标
Oracle 游標有三種:顯示游標、隱式游標、參照游標。
fetch...bulk collect into
?
select 語句會把結果集全部返回給用戶,而無法對結果集中的每行數據進行單獨的操作。因此游標可以解決此問題。
隱式游標是在執行DML SQL語句時,Oracle自動創建的,名字固定叫sql
顯示游標由用戶自行創建
REF游標:REF游標用于處理運行時才能確定的動態SQL查詢的結果
一、隱式游標
隱式游標包含的屬性有:
%FOUND? :SQL語句影響了一行或者多行時為ture
%NOTFOUND :SQL語句沒有影響任何行時為ture
%ROWCOUNT :SQL語句影響的行數
%ISOPEN : 游標是否打開
?
新建表:
declaresql_command varchar2(500);isExsit number ; beginselect 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..13000loopinsert 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; /?
--隱式游標示例 beginupdate salary_tbl set DEPARTMENT ='部門3' where DEPARTMENT ='部門3';if sql%found thendbms_output.put_line('修改了'||sql%ROWCOUNT||'行');end if;rollback; end; /?
二、顯示游標
首先需要定義游標,然后打開游標,此時游標就指向了某個結果集。此時一行一行地讀取,讀完之后再關閉游標。
cursor curname (參數集)?is SQLstatement;
----把領導者的薪資變成99999---- declaresal salary_tbl.employer_nm%type;cursor mycur is select distinct LEADER_NM from salary_tbl ; beginopen mycur;fetch mycur into sal;while mycur%found loopupdate salary_tbl set salary=99999 where employer_nm = sal;fetch mycur into sal;end loop;close mycur; end; /傳參的顯示游標示例:
----把除了部門9的領導者的薪資變成8888---- declaresal 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; beginopen mycur(9);fetch mycur into sal;while mycur%found loopupdate salary_tbl set salary=8888 where employer_nm = sal;fetch mycur into sal;end loop;close mycur; end; /上面都是利用游標來查詢,游標還可以用來更新刪除操作。
cursor curname (參數集)?is SQLstatement for update;
current of?curname
?
----把除了部門8的領導者薪資變成7777---- declaresal 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; beginopen mycur(8);fetch mycur into sal;while mycur%found loopupdate salary_tbl set salary=7777 where current of mycur;fetch mycur into sal;end loop;close mycur; end; /循環游標只能用于查詢但是大大簡化代碼:
----把除了部門7的領導者薪資變成6666---- declaresal 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; beginfor c1 in mycur(7) loopupdate salary_tbl set salary=6666 where current of mycur;end loop; end; /練習:利用游標來初始化表,新建部門表(部門號,員工總薪資,領導人員)
declaresql_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; beginselect 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; /三、參照游標
當無法直接確定游標的定義時可以使用參考游標;
定義:TYPE??typename? IS REF CURSOR;
typename refcursorname;
賦值: OPEN?refcursorname? ?FOR? ?sqlstatement;
例如:初始化 DEPARTMENT_TBL.leaders? ? 獲取部門下的所有領導者.;
---初始化部門中的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;elseleadernm := 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; /新表的結果如圖:
總結
以上是生活随笔為你收集整理的Oracle 原理:游标,显示游标、隐式游标、参照游标的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oracle 原理: 过程和函数
- 下一篇: Oracle 原理: 集合数组,集合属性