Oracle數據庫的游標和for循環使用


 

1. 游標的概念和作用

  • 游標是 sql 的一個內存工作區,由系統或用戶以變量的形式定義
  • 游標的作用就是用於臨時存儲從數據庫中提取的數據塊(結果集)。
  • 它有一個 指針,從上往下移動(fetch),從而能夠遍歷每條記錄。
  • 用 犧牲內存 來提升 SQL 執行效率,適用於 大數據處理。

    (摘抄自https://blog.csdn.net/qq_34745941/java/article/details/81294166)。 

2.游標結構圖

 

 

 3.具體用法

  游標有四大屬性,分別是

       1. “SQL%ISOPEN” :布爾類型。判斷游標是否打開

  2.“SQL%FOUND”:布爾類型。判斷上一條fetch語句是否有值,有則為true,否則為false;

  3.“SQL%NOTFOUND”:布爾類型。與2相反,常用作退出循環的條件。

  4.“SQL%ROWCOUNT”:整型。當前成功執行更改的數據行數。

  3.1 靜態游標

   3.1.1 隱式游標

    使用DML操作(增刪改)或select……into……會自動創建隱式游標,名稱是“sql”,該游標會自動聲明,打開和關閉。無需人為開啟或關閉。

    

create or replace procedure ATest(
 O_Result  Out VarChar2
)is 
 v_id staff.id%type;
begin
  insert into staff(id,name) values(1,'張三');
  if sql%found then
     O_Result:='添加成功';
  end if;
     
  update staff set name = '李四'where id = 1;
  if sql%found then
     O_Result:='更新成功';
  end if;
  
  delete from staff where id = 1;
  if sql%found then
     O_Result:='刪除成功';
  end if;
  
  select id into v_id from staff;
  if sql%found then
     O_Result:='查詢成功';
  end if;
  
  if sql%isopen then
     O_Result:='游標為開啟狀態,但不可能走到這一步';   --游標只有在執行上述增刪改操作才會開啟並自動關閉
  else
     O_Result:='游標為關閉狀態';
  end if;

exception
  when Others then
  begin
    O_Result:='N_SQLCODE is '||SQLCODE||' and SQLERRM is '||SQLERRM;
    rollback;
  end;
end;

 

  3.1.2 顯式游標

  顯示游標又分為不帶參數和帶參數兩種

  無參:

create or replace procedure ATest(
 O_Result  Out VarChar2
)is 
 v_cur_info staff%rowtype;
 cursor v_cur is       --聲明游標 為staff表的數據集
     select * from staff;
begin
      open v_cur; --打開游標
      
      fetch v_cur into v_cur_info; --賦值給游標
      
       O_Result:='ID:'||v_cur_info.id||',Name:'||v_cur_info.name;--輸出值
      close v_cur; --關閉游標

exception
  when Others then
  begin
    O_Result:='N_SQLCODE is '||SQLCODE||' and SQLERRM is '||SQLERRM;
    rollback;
  end;
end;

輸出結果: ID:1,Name:張三

帶參:

create or replace procedure ATest(
 O_Result  Out VarChar2
)is 
 v_cur_info staff%rowtype;
 cursor v_cur(v_id staff.id%type) is       --聲明游標 為staff表的數據集
     select * from staff where id =v_id;   --參數:v_id
begin
      open v_cur(1); --打開游標
      
      fetch v_cur into v_cur_info; --賦值給游標
      
       O_Result:='ID:'||v_cur_info.id||',Name:'||v_cur_info.name;
      close v_cur; --關閉游標

exception
  when Others then
  begin
    O_Result:='N_SQLCODE is '||SQLCODE||' and SQLERRM is '||SQLERRM;
    rollback;
  end;
end;

輸出結果: ID:1,Name:張三

  3.2 動態游標

  3.2.1 自定義類型游標

    自定義游標類型聲明寫法:

TYPE ref_type_name IS REF CURSOR

[RETURN return_type];

ref_type_name代表我們自定義類型的名稱,cursor是系統默認的

return_type代表數據庫表中的一行,或一個記錄類型,是一個返回類型;

返回值不是必要的,無返回值則稱為弱類型,更加靈活;有返回值稱為強類型,減少錯誤;

弱類型寫法

create or replace procedure ATest(
 O_Result  Out VarChar2
)is 
 v_cur_info staff%rowtype;
 type v_cur_type is ref cursor;  --自定義游標類型
 v_cur v_cur_type; 
begin
      open v_cur for             --打開游標並聲明
      select * from staff where id<5;
      loop                       --開始循環
        fetch v_cur into v_cur_info;    -- 賦值
        exit when v_cur%notfound;       --判斷沒有值就退出循環
        O_Result:= O_Result||chr(10)|| 'ID:'||v_cur_info.id||',Name:'||v_cur_info.name;
      end loop;
    close v_cur;  
exception
  when Others then
  begin
    O_Result:='N_SQLCODE is '||SQLCODE||' and SQLERRM is '||SQLERRM;
    rollback;
  end;
end;

另一種寫法:

create or replace procedure ATest(
 O_Result  Out VarChar2
)is 
 v_sql varchar(1000);
 v_param staff.id%type:=5;
 v_cur_info staff%rowtype;
 type v_cur_type is ref cursor;  --自定義游標類型
 v_cur v_cur_type; 
begin
  v_sql:='select * from staff where id <:id';
  
      open v_cur for v_sql            --打開游標並聲明
      using v_param;                  --綁定參數方法
      loop                       --開始循環
        fetch v_cur into v_cur_info;    -- 賦值
        exit when v_cur%notfound;       --判斷沒有值就退出循環
        O_Result:= O_Result||chr(10)|| 'ID:'||v_cur_info.id||',Name:'||v_cur_info.name;
      end loop;
    close v_cur;  
exception
  when Others then
  begin
    O_Result:='N_SQLCODE is '||SQLCODE||' and SQLERRM is '||SQLERRM;
    rollback;
  end;
end;

強類型寫法:

    三個注意事項:

   1.強類型無法使用綁定參數方法

 2.for后面必須是sql,不能是字符串,如上面的v_sql;

 3.參數必須對應;

create or replace procedure ATest(
 O_Result  Out VarChar2
)is 
 v_cur_info staff%rowtype;
 type v_cur_type is ref cursor return staff%rowtype ;  --自定義游標類型
 v_cur v_cur_type; 
begin
  
      open v_cur for  --打開游標並聲明
      select * from staff where id <5;           
      loop                       --開始循環
        fetch v_cur into v_cur_info;    -- 賦值
        exit when v_cur%notfound;       --判斷沒有值就退出循環
        O_Result:= O_Result||chr(10)|| 'ID:'||v_cur_info.id||',Name:'||v_cur_info.name;
      end loop;
    close v_cur;  
exception
  when Others then
  begin
    O_Result:='N_SQLCODE is '||SQLCODE||' and SQLERRM is '||SQLERRM;
    rollback;
  end;
end;

  3.2.2 系統類型游標

  簡寫手動聲明自定義游標的過程

 type v_cur_type is ref cursor return staff%rowtype ;  --自定義游標類型
 v_cur v_cur_type; 
等同於
v_cur sys_refcursor; 

4.效率問題

沒有實際測試過,根據其他博客總結是這樣:一般來說批量處理的速度要最好,隱式游標的次之,單條處理的最差

 以下是示例:

1、批量處理
open 游標;
loop
   fetch 游標 bulk collect into 集合變量(也就是 table 類型哦) limit 數值; -- 一般 500 左右
   exit when 條件 --(變量.count = 0,如果用 sql%notfound 不足 limit 的記錄就不會被執行哦)
close 游標;

2、隱式游標
for x in (sql 語句) loop
... 邏輯處理
end loop;

3、單條處理
open  游標;
loop
   fetch 游標 into 變量;
   exit when 條件
end loop;
close 游標;
————————————————
原文鏈接:https://blog.csdn.net/qq_34745941/java/article/details/81294166

批量處理的關鍵字不是很了解,下次學習下在記錄起來;

隱式游標寫法最簡潔明了,類似於程序中的for循環寫法;

單條處理大概就是上面那些范例的寫法。

(如果有錯誤,再回來改正)。

內容參考於https://blog.csdn.net/qq_34745941/article/details/81294166

      https://www.cnblogs.com/heshan664754022/archive/2013/05/22/3092437.html

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

------------恢復內容結束------------


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM