Oracle --遊標

爲了處理SQL語句獲得的信息,oracle必需要分配一片叫作上下文的區域來處理如上信息。遊標是一個指向上下文的句柄或指針,經過遊標,pl/sql能夠控制上下文區域所獲得的信息。sql

1.對於不一樣的SQL語句,遊標的使用狀況也不一樣
oracle

SQL語句                              遊標oop

非查詢語句                           隱式遊標fetch

結果是單行的查詢語句           隱式或顯示遊標指針

結果是多行的查詢語句           顯示的code

2.處理顯示遊標ip

declare
        --定義遊標類型
        cursor c_cursor is select user_name,age from t_user;
        --定義兩個變量
        v_userName t_user.user_name%type;
        v_age            t_user.age%type; 
begin
        --打開遊標
        open c_cursor;
        --提取遊標數據,即檢索結果集中的數據行,放入到指定的輸出變量中
        fetch c_cursor into v_userName,v_age;
        --這裏能夠理解c_cursor就是select user_name,age from t_user
        --即下面的c_cursor能夠用select user_name,age from t_user代替
        --當select語句找獲得值時,就loop
        while c_cursor%found loop
                dbms_output.put_line('執行本身的操做');
                fetch c_cursor into v_userName,v_age;
        end loop;
        --關閉遊標
        close c_cursor;        
end;

3.遊標屬性內存

%found  布爾型屬性,當最近一次讀記錄成功時返回trueit

%notfound  與%found相反io

%isopen  布爾型屬性,當遊標已打開時返回true

%rowcount  數字型屬性,返回已從遊標中讀取的記錄數

例如:給工資低於4000員工增長工資800

declare
        v_empNo emp.empNo%type;
        v_salary emp.salary%type;
        cursor c_cursor is select empNo,salary from emp;
begin
        open c_cursor;
        loop
            fetch c_cursor into v_empNo,v_salary;
            --當遊標沒有找到數據時,中止
            exit when c_cursor%notfound;
            if v_salary <=4000 then
                update emp 
                set salary=salary+800
                where empNo=v_empNo; 
            end if;
        end loop;  
        close c_cursor;  
end;

 4.遊標for循環

pl/sql語言提供了遊標for循環語句,它會自動執行遊標的open、fetch、close語句。當進入循環時,for循環語句自動打開遊標,並提取第一行的遊標數據,當程序處理完當前所提取的數據進入下一次循環時,遊標for循環語句自動提取下一行數據進行處理,當提取完結果集中全部數據行後結束循環,並自動關閉遊標。

declare
        cursor c_cursor is select empNo,empName,empSalary from emp;
begin
        --隱含打開遊標
        for v_salary in c_cursor loop
        --隱含執行fetch語句
        dbms_output.put_line('執行本身的操做'); 
        --隱含監測c_cursor%notfound語句
        end loop;
        --隱含關閉遊標
end;

5.隱式遊標處理

顯示遊標主要是用於對查詢語句的處理,尤爲是在查詢結果爲多條記錄的狀況。而對於非查詢語句,如修改、刪除操做等,則由oracle系統自動的爲這些操做設置遊標並建立其工做區,這些由系統隱含建立的遊標稱爲隱式遊標,隱式遊標的名字爲SQL,這是由oracle系統定義的。對於隱式遊標的操做,如定義、打開、取值及關閉操做,都由oracle系統自動完成,用戶只能經過隱式遊標的相關屬性來完成相應的操做。

實際例子

刪除emp表中某部門的全部員工,若是該部門中沒有員工,則在dept表中刪除該部門。

declare
        v_deptNo emp.deptNo%type;
begin
        delete from emp where deptNo = v_deptNo;
        --若是如上where語句不成立,即v_deptNo字段中沒有員工
        if SQL%notfound then
            --在部門表中刪除該部門號
            delete from dept where deptNo = v_deptNo;
        end if;
end;

6.no_data_found與%notfound的區別

select ... into 語句會觸發no_data_found;

當一個顯示遊標的where子句未找到時會觸發%notfound;

當update或delete語句的where子句未找到時會觸發SQL%notfound。

7.遊標變量

遊標變量是一個指向多行查詢結果集中當前數據行的指針。

1>遊標變量是動態的,遊標是靜態的。

2>遊標只能與指定的查詢相連,即固定指向一個查詢的內存處理區域;而遊標變量是動態的,它能夠與不一樣的查詢語句相連,它能夠指向不一樣的查詢語句的內存處理區域(同一時刻只能與一個查詢語句相連,且要求這些查詢語句的返回類型兼容)。

在定義遊標變量時,有強類型定義和弱類型定義兩種。強類型定義必須指定遊標變量的返回值類型,而弱類型定義則不用說明返回類型。

例如,建立兩個強類型、一個弱類型遊標變量

--定義一個遊標變量,返回類型是表t_dept類型
type c_deptType is ref cursor return t_dept%rowtype; 
--定義一個遊標變量,返回類型是t_dept表字段
type c_deptType2 is ref cursor return t_dept.deptName%type;
--定義一個遊標變量,無返回類型
type c_deptType3 is ref cursor;

 強類型遊標變量舉例

declare
        type emp_rec is record(
        empId emp.empNo%type;
        empName emp.empName%type;
        empJob emp.empJob%type
        );
        --定義遊標變量,返回類型emp_rec
        type empRefcurType is ref cursor return emp_rec;
        --定義遊標變量,類型爲empRefcurType 
        emp_refcur empRefcurType;
        --定義變量,類型爲emp_rec
        emp_job emp_rec;
begin
        open emp_refcur for
        select empNo,empName,empJob from emp;
        fetch emp_refcur into emp_job;
        while emp_refcur%found loop
                dbms_output.put_line('執行本身的操做');    
                fetch emp_refcur into emp_job;
        end loop;        
end;

弱類型遊標變量舉例

declare
        type c_refcur if ref cursor;
        refcur c_refcur;
        type sample_refType is record(
        v_id number(2);
        v_description varchar2(30)
        );
        sample sample_refType;
begin
        open refcur for
        select deptNo,deptName from dept;
        fetch refcur into sample;
        while refcur%found loop
               dbms_output.put_line('執行本身的操做'); 
                fetch refcur into sample; 
         end loop;
         close refcur;                   
end;
相關文章
相關標籤/搜索