PL/SQL developer基礎語法學習(三)之遊標

一、遊標分爲:隱式遊標和顯示遊標

1.隱式遊標:發生與操作的DML語句中 sql遊標

例子(實例中的表都是使用的oracle中的初始表):

declare
     --拷貝emp的結構+記錄
     v_sql varchar2(100) :='create table emp_copy2 as select * from emp where 1=1';
     --更新記錄
     v_update_sql varchar2(100) :='update emp_copy2 set sal =sal+1000 where empno=&empno';
begin
     --創建表 (存在記錄的cud 就存在sql遊標)
     execute immediate v_sql;
     dbms_output.put_line('更新了'||sql%rowcount||'條記錄');     
     --更新記錄  (隱式存在SQL遊標)
     execute immediate v_update_sql;
     dbms_output.put_line('更新了'||sql%rowcount||'條記錄');     
     commit;
     --查看狀態
     if not sql%isopen then
         dbms_output.put_line('隱式遊標自動關閉');
     end if;
         --刪除表
     execute immediate 'drop table emp_copy2 cascade constraints';     

exception 
   when  no_data_found then
        dbms_output.put_line('數據未找到'||sqlcode||'-->'||sqlerrm);  
        rollback;
   when too_many_rows then
        dbms_output.put_line('數據超出'||sqlcode||'-->'||sqlerrm);  
         rollback;
   when others then
        dbms_output.put_line('其他異常'||sqlcode||'-->'||sqlerrm);  
         rollback;
end;

2.顯示遊標:可分爲靜態遊標和動態遊標(ref遊標)

(1)靜態遊標:可分爲有參和無參

1)實例(無參)

declare 
      --創建並聲明
      cursor  cur_emp is select ename,sal,dname,loc from emp_copy e  join dept d  on e.deptno=d.deptno where e.deptno=20;
begin 
      --不用打開 不用聲明變量  不用抓取 不用關閉
      for v_emp in cur_emp loop
          dbms_output.put_line(v_emp.ename||'-->'||v_emp.sal||'-->'||v_emp.dname||'-->'||v_emp.loc);
      end loop;

exception 
   when  no_data_found then
        dbms_output.put_line('數據未找到'||sqlcode||'-->'||sqlerrm);  
        rollback;
   when too_many_rows then
        dbms_output.put_line('數據超出'||sqlcode||'-->'||sqlerrm);  
         rollback;
   when others then
        dbms_output.put_line('其他異常'||sqlcode||'-->'||sqlerrm);  
         rollback;
end;

2)實例(有參):

declare 
      --創建並聲明
      cursor  cur_emp(v_deptno dept.deptno%type) is select ename,sal,dname,loc from emp_copy e  join dept d  on e.deptno=d.deptno where e.deptno=v_deptno;
begin 
      --不用打開 不用聲明變量  不用抓取 不用關閉
      for v_emp in cur_emp(&部門編號) loop
          dbms_output.put_line(v_emp.ename||'-->'||v_emp.sal||'-->'||v_emp.dname||'-->'||v_emp.loc);
      end loop;

exception 
   when  no_data_found then
        dbms_output.put_line('數據未找到'||sqlcode||'-->'||sqlerrm);  
        rollback;
   when too_many_rows then
        dbms_output.put_line('數據超出'||sqlcode||'-->'||sqlerrm);  
         rollback;
   when others then
        dbms_output.put_line('其他異常'||sqlcode||'-->'||sqlerrm);  
         rollback;
end;

3)更新(操作數據)
更新(update和delete)遊標 :
a)、遊標聲明時加入: for update
b)、操作記錄指向當前行: where current of 遊標
實例:

--更新遊標操作
declare 
      --創建並聲明
      cursor  cur_emp(v_deptno emp.deptno%type) is select * from emp_copy e where e.deptno=v_deptno for update;
begin 
      --不用打開 不用聲明變量  不用抓取 不用關閉
      for v_emp in cur_emp(&部門編號) loop
         update emp_copy set sal=sal+500 where current of cur_emp;
      end loop;
      commit;
exception 
   when  no_data_found then
        dbms_output.put_line('數據未找到'||sqlcode||'-->'||sqlerrm);  
        rollback;
   when too_many_rows then
        dbms_output.put_line('數據超出'||sqlcode||'-->'||sqlerrm);  
         rollback;
   when others then
        dbms_output.put_line('其他異常'||sqlcode||'-->'||sqlerrm);  
         rollback;
end;

(2).動態遊標ref:又分爲強類型和弱類型
動態遊標: 在使用過程中,動態關聯結果集

1.弱類型和強類型的區別:
弱類型: 隨意關聯結果集
強類型: 同一個範圍內的 結果集

實例(弱類型)

declare 
    --1、創建遊標類型
    type ref_emp is ref cursor;
    --2、聲明變量
    v_cur_emp ref_emp;  

    v_emp emp%rowtype;
    v_dept dept%rowtype;

    v_flag number(5) :=&選擇請輸入10;
begin 
    if  v_flag=1 then
       --3、打開遊標  關聯結果集
        open v_cur_emp for select * from emp where sal>1000;
       --4、操作
       loop
             fetch v_cur_emp into v_emp;
             exit when v_cur_emp%notfound;
             dbms_output.put_line(v_emp.ename);
       end loop;   
   else    
       --再次使用遊標
       open v_cur_emp for select * from dept;
        --4、操作
       loop
             fetch v_cur_emp into v_dept;
             exit when v_cur_emp%notfound;
             dbms_output.put_line(v_dept.dname);
       end loop;   
   end if;
   --5、關閉遊標
   close v_cur_emp;   

exception 
   when  no_data_found then
        dbms_output.put_line('數據未找到'||sqlcode||'-->'||sqlerrm);  
        rollback;
   when too_many_rows then
        dbms_output.put_line('數據超出'||sqlcode||'-->'||sqlerrm);  
         rollback;
   when others then
        dbms_output.put_line('其他異常'||sqlcode||'-->'||sqlerrm);  
         rollback;
end;

實例(強類型)

declare 
    --1、創建強類型ref遊標
    type ref_emp is ref cursor return emp%rowtype;
    --2、聲明變量
    v_cur_emp ref_emp;  

    v_emp emp%rowtype;   
    v_flag number(5) :=&選擇請輸入10;
begin 
    if  v_flag=1 then
       --3、打開遊標  關聯結果集
        open v_cur_emp for select * from emp where sal>3000;
         dbms_output.put_line('--------工資大於3000的員工名稱----------');      
   else    
       --再次使用遊標 (同類型結果集)
       open v_cur_emp for select * from emp where comm is not null;  
       dbms_output.put_line('--------存在佣金的員工名稱----------');         
   end if;

    --4、操作
     loop
           fetch v_cur_emp into v_emp;
           exit when v_cur_emp%notfound;
           dbms_output.put_line(v_emp.ename||'-->'||v_emp.comm);
     end loop;   
   --5、關閉遊標
   close v_cur_emp;   

exception 
   when  no_data_found then
        dbms_output.put_line('數據未找到'||sqlcode||'-->'||sqlerrm);  
        rollback;
   when too_many_rows then
        dbms_output.put_line('數據超出'||sqlcode||'-->'||sqlerrm);  
         rollback;
   when others then
        dbms_output.put_line('其他異常'||sqlcode||'-->'||sqlerrm);  
         rollback;
end;

靜態遊標和動態遊標的區別:
1、 不是創建時關聯結果集,打開時關聯結果集 。不能使用for
2、 先創建遊標類型 再聲明遊標變量。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章