oracle中游標的使用

一 遊標是什麼 

遊標字面理解就是遊動的光標。 

用數據庫語言來描述:遊標是映射在結果集中一行數據上的位置實體,有了遊標,用戶就可以訪問結果集中的任意一行數據了,將遊標放置到某行後,即可對該行數據進行操作,例如提取當前行的數據等。 

二 遊標的分類 

顯式遊標和隱式遊標 

顯式遊標的使用需要4步: 

1. 聲明遊標 

CURSOR mycur(vartype number) is 
select emp_no,emp_zc from cus_emp_basic 
where com_no = vartype; 



2. 打開遊標 

open mycur(000627) 

注:000627是參數 

3. 讀取數據 

fetch mycur into varno, varprice; 

4. 關閉遊標 

close mycur; 

三 遊標的屬性 

oracle 遊標有4個屬性:%ISOPEN,%FOUND,%NOTFOUND,%ROWCOUNT。 

%ISOPEN判斷遊標是否被打開,如果打開%ISOPEN等於true,否則等於false; 

%FOUND %NOTFOUND判斷遊標所在的行是否有效,如果有效,則%FOUNDD等於true,否則等於false; 

%ROWCOUNT返回當前位置爲止遊標讀取的記錄行數。 

四 示例 

set serveroutput on; 
declare 
varno varchar2(20); 
varprice varchar2(20); 

CURSOR mycur(vartype number) is 
select emp_no,emp_zc from cus_emp_basic 
where com_no = vartype; 
begin 

if mycur%isopen = false then 
open mycur(000627); 
end if; 

fetch mycur into varno,varprice; 
while mycur%found 
loop 
dbms_output.put_line(varno||','||varprice); 
if mycur%rowcount=2 then 
exit; 
end if; 
fetch mycur into varno,varprice; 
end loop; 

close mycur; 
end; 



PL/SQL記錄的結構和C語言中的結構體類似,是由一組數據項構成的邏輯單元。 

PL/SQL記錄並不保存在數據庫中,它與變量一樣,保存在內存空間中,在使用記錄時候,要首先定義記錄結構,然後聲明記錄變量。可以把PL/SQL記錄看作是一個用戶自定義的數據類型。 

set serveroutput on; 
declare 

type person is record 

empno cus_emp_basic.emp_no%type, 
empzc cus_emp_basic.emp_zc%type); 

person1 person; 

cursor mycur(vartype number)is 
select emp_no,emp_zc from cus_emp_basic 
where com_no=vartype; 

begin 
if mycur%isopen = false then 
open mycur(000627); 
end if; 

loop 
fetch mycur into person1; 
exit when mycur%notfound; 
dbms_output.put_line('僱員編號:'||person1.empno||',地址:'||person1.empzc); 
end loop; 

close mycur; 
end; 



典型遊標for 循環 

遊標for循環示顯示遊標的一種快捷使用方式,它使用for循環依次讀取結果集中的行數據,當form循環開始時,遊標自動打開(不需要open),每循環一次系統自動讀取遊標當前行的數據(不需要fetch),當退出for循環時,遊標被自動關閉(不需要使用close)。使用遊標for循環的時候不能使用open語句,fetch語句和close語句,否則會產生錯誤。 

set serveroutput on; 
declare 

cursor mycur(vartype number)is 
select emp_no,emp_zc from cus_emp_basic 
where com_no=vartype; 

begin 
for person in mycur(000627) loop 
dbms_output.put_line('僱員編號:'||person.emp_no||',地址:'||person.emp_zc); 
end loop; 
end;

==================================================================================

實例:

FROM  Rs_Employees
    
 Where  HeTongId = ' WL-090001 ' ;
  
  
 if  sql % Notfound  then 
    Dbms_Output.put_line(
 ' 沒有找到要刪除的記錄 ' );
  
 else 
    Dbms_Output.put_line(
 ' 已刪除記錄 ' );
  
 end   if ;

 END ;
   
   
   
 -- 例七:%RowCount,查詢記錄行數 
 
Declare 
  v_name Rs_Employees.Name
 % type;
 BEGIN 
  
 SELECT  Name  Into  v_Name
    
 FROM  Rs_Employees
    
 Where  HeTongId = ' WL-090010 ' ;
  
  
 if  sql % RowCount   > 0   Then 
    Dbms_Output.put_line(
 ' 已從表中選擇行,Name爲: ' || v_Name);
  
 else 
    Dbms_Output.put_line(
 ' 從表中未選擇行 ' );
  
 end   if ;

 END ;
   
 -- 再演示以下代碼 
 
BEGIN 
  
 DELETE   FROM  Rs_Employees
    
 Where  HeTongId <= ' WL-090010 ' ;
  
  Dbms_Output.put_line(
 ' 已從表中刪除 ' || To_Char(sql % RowCount ) || ' 條記錄 ' );
 END ;   
   
 
 
 -- 例八:顯式遊標 
--
 以下示例在所有遊標的記錄中的Name字段中加一字串 
--
 同時在此示範瞭如何使用%NotFound屬性 
--
 set serveroutput on; 
 
Declare 
  v_Id    Rs_Employees.Hetongid
 % type;
  v_name  Rs_Employees.Name
 % type;
  v_Count 
 Number : = 0 ;
  
  
 Cursor  MyCur  Is 
    
 SELECT  HetongId,Name  FROM  Rs_Employees
      
 Where  HeTongId <= ' WL-090010 ' ;
      
 BEGIN 
  
 -- 打開遊標  
 
   Open  MyCur;
  
 -- 進入循環 
 
  Loop
    
 Fetch  MyCur  Into  v_id,v_name;
    
 Exit   When  MyCur % NotFound;
    
    
 Update  Rs_Employees
      
 Set  Name  =  Name  ||   ' X ' 
      
 Where  HeTongId = v_Id;
    v_Count :
 =  v_Count  +   1 ;
  
 End  Loop;
  
  Dbms_Output.put_line(
 ' 已更新 ' || v_Count || '  ' );
 END ;

 -- 例10:以下示範%RowCount和%IsOpen,同時示範了%RowType的使用 
--
 例10:以下示例%RowCount 
 
Declare 
  v_Row   Rs_Employees
 % RowType;
 
  
 Cursor  MyCur  Is 
    
 SELECT   *   FROM  Rs_Employees
      
 Where  HeTongId <= ' WL-090010 ' ;
 BEGIN 
  
 if   Not  MyCur % IsOpen  then 
    Dbms_Output.put_line(
 ' 遊標未打開 ' );
    
 -- 打開遊標  
 
     Open  MyCur;
  
 end   if ;

  
 -- 進入循環 
 
  Loop
    
 Fetch  MyCur  Into  v_row;
    
 Exit   When  MyCur % NotFound;
  
    Dbms_Output.put_line(
 ' 當前已取得 ' || MyCur % RowCount || '  ' );
    Dbms_Output.put_line(
 ' 姓名: ' || v_row.Name || '      ' || ' 合同號: ' || v_row.HeTongId);
    Dbms_Output.put_line(
 '' );
  
 End  Loop;
  
  Dbms_Output.put_line(
 ' 總共已取得 ' || MyCur % RowCount || '  ' );
  
  
 if  MyCur % IsOpen  then 
    Dbms_Output.put_line(
 ' 遊標已打開 ' );
    
 Close  MyCur;
  
 end   if ;

  
 if   Not  MyCur % IsOpen  then 
    Dbms_Output.put_line(
 ' 遊標已關閉 ' );
  
 end   if ;
  
 END ;

 -- 例12:查詢嵌套表中數據的遊標 
--
 1 創建類型 
 
   CREATE   OR   REPLACE  TYPE emp_type  As  Object 
   (eno   
 number ,
    ename 
 varchar2 ( 20 ),
    esal  
 number );
 -- 2 使用Table of 子句創建Table類型 
 
   CREATE  TYPE emp_nt  AS   Table   Of  emp_type;
 -- 3 使用emp_nt數據類型創建myemp表 
 
   CREATE   TABLE  myemp
   (deptno     
 number ,
    edet       emp_nt)
    NESTED 
 TABLE  edet Store  As  myemployee;
 -- 4 初始化myemp的數據 
 
   Insert   Into  myemp  values 
    (
 10 ,emp_nt(emp_type( 1000 , ' James '  10000 ),
               emp_type(
 1001 , ' Daniel ' , 20000 )));
  
 Commit ;
  
 -- 執行下列代碼   
 
Declare 
  sal  
 number ;
  ena  
 varchar2 ( 20 );
  
  
 Cursor  MyCur  Is 
    
 SELECT  a.esal,a.ename
      
 FROM  the 
      (
 Select  edet  From  myemp
         
 Where  deptno = 10 ) a;
 BEGIN 
  
 -- 打開遊標  
 
   Open  MyCur;
  
 -- 進入循環 
 
  Loop
    
 Fetch  MyCur  Into  sal,ena;
    
 Exit   When  MyCur % NotFound;
    Dbms_Output.put_line(ena
 || '      ' || sal);
  
 End  Loop;
  
  
 Close  MyCur;
 END ;




 -- 例13:此例改自例10,示範循環遊標的用法 
 
Declare 
  
 Cursor  MyCur  Is 
    
 SELECT   *   FROM  Rs_Employees
      
 Where  HeTongId <= ' WL-090010 ' ;
 BEGIN 
 
  
 For  tmp_cur  In  MyCur
  Loop
    Dbms_Output.put_line(
 ' 當前已取得 ' || MyCur % RowCount || '  ' );
    Dbms_Output.put_line(
 ' 姓名: ' || tmp_cur.Name || '      ' || ' 合同號: ' || tmp_cur.HeTongId);
  
 End  Loop;

  
 -- 在這種情況下,下面這條語句不能執行 
 
   -- Dbms_Output.put_line('當前已取得'||MyCur%RowCount||'行'); 
 
END ;


 -- 再示範帶參數的遊標 
 
Declare 
  
 Cursor  MyCur(m_HeTongId Rs_Employees.Hetongid % type)  Is 
    
 SELECT   *   FROM  Rs_Employees
      
 Where  HeTongId <= m_HeTongId;
 BEGIN 
 
  
 For  tmp_cur  In  MyCur( ' WL-090020 ' )
  Loop
    Dbms_Output.put_line(
 ' 當前已取得 ' || MyCur % RowCount || '  ' );
    Dbms_Output.put_line(
 ' 姓名: ' || tmp_cur.Name || '      ' || ' 合同號: ' || tmp_cur.HeTongId);
  
 End  Loop;

  
 -- 在這種情況下,下面這條語句不能執行 
 
   -- Dbms_Output.put_line('當前已取得'||MyCur%RowCount||'行'); 
 
END ;


 -- 再示範以下寫法 
--
 在循環遊標中使用查詢 
 
Declare 
  v_HeTongId  Rs_Employees.Hetongid
 % type;
 BEGIN 
  v_HeTongId :
 =   ' WL-090020 ' ;
  
  
 For  tmp_cur  In  ( SELECT   *   FROM  Rs_Employees
                    
 Where  HeTongId <= v_HeTongId)
  Loop
    Dbms_Output.put_line(
 ' 姓名: ' || tmp_cur.Name || '      ' || ' 合同號: ' || tmp_cur.HeTongId);
  
 End  Loop;
 END ;





 -- 例15:示範遊標變量 
--
 此例要在Command window或Sql Plus中示範,結果會有點區別 
--
 SET SERVEROUTPUT ON; 
 
Declare 
  TYPE r1_cur 
 IS  REF  CURSOR ;
  var1 r1_cur;
  no     
 varchar2 ( 20 );
  
  v_czy  sc_chukudan.czy
 % type;
  v_pid  sc_chukudanDetail.Productid
 % type;
  
 BEGIN 
  no :
 =   ' &你選擇的 ' ;

  
 IF   UPPER (no)  =   ' MASTER '   then 
    
 OPEN  var1  For 
      
 Select  Czy  FROM  sc_chukudan
        
 Where  ChuKuDanId  =   ' SCKD04020001 ' ;
    
 FETCH  var1  into  v_Czy;
    Dbms_Output.put_line(
 ' 操作員是: ' || v_czy);
    
 CLOSE  var1;
  
 ELSE 
    
 OPEN  var1  For 
      
 Select  Productid  FROM  sc_chukudanDetail
        
 Where  ChuKuDanId  =   ' SCKD04020001 ' ;
    LOOP
      
 FETCH  var1  into  v_pid;
      
 EXIT   WHEN  var1 % NotFound;
      Dbms_Output.put_line(
 ' 生產通知單ID是: ' || v_pid);
    
 END  LOOP;
    
 CLOSE  var1;
  
 END   IF ;    
 END ;



 -- 例16: 遊標中的更新和刪除 
--
 此例改自例8 
 
Declare 
  
 -- 當打開此遊標,將鎖住了相關記錄 
 
   Cursor  MyCur  Is 
    
 SELECT  Name  FROM  Rs_Employees
      
 Where  HeTongId <= ' WL-090010 ' 
      
 For   Update   OF  Name;
      
 BEGIN 
  
 For  tmp_cur  in  MyCur
  Loop
    
 Update  Rs_Employees
      
 Set  Name  =  Name  ||   ' X ' 
      
 Where   Current   of  MyCur;
  
 End  Loop;
 END ;


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