Oracle遊標解析

本節對Oracle中的遊標進行詳細講解。

本節所舉實例來源Oracle中scott用戶下的emp表dept表:

1、遊標:

一、概念:

遊標的本質是一個結果集resultset,主要用來臨時存儲從數據庫中提取出來的數據塊。

2、遊標的分類:

一、顯式遊標:由用戶定義,須要的操做:定義遊標、打開遊標、提取數據、關閉遊標,主要用於對查詢語句的處理。

屬性:%FOUND        %NOTFOUND        %ISOPEN          %ROWCOUNT

Example:打印emp表的員工信息

DECLARE
  CURSOR emp_cursor IS SELECT empno,ename,job FROM emp;
  v_empno emp.empno%TYPE;
  v_name emp.ename%TYPE;
  v_job emp.job%TYPE;
BEGIN
  OPEN emp_cursor;
  LOOP
    FETCH emp_cursor INTO v_empno,v_name,v_job;
    DBMS_OUTPUT.PUT_LINE('員工號爲:'||v_empno||'姓名是'||v_name||'職位:'||v_job);
    EXIT WHEN emp_cursor%NOTFOUND;
  END LOOP;
  CLOSE emp_cursor;
END; 

這裏嚴格按照顯示遊標的書寫規則:DECLARE emp_cursor定義遊標OPEN emp_cursor打開遊標FETCH emp_cursor INTO...提取數據CLOSE emp_cursor關閉遊標,由於提取出來的數據屬於多行,因此經過loop循環打印便可。

Example2:檢驗遊標是否打開,若是打開顯示提取行數

DECLARE
  CURSOR emp_cursor IS SELECT empno,ename,job FROM emp;
  v_empno emp.empno%TYPE;
  v_name emp.ename%TYPE;
  v_job emp.job%TYPE;
BEGIN
  OPEN emp_cursor;
  LOOP
       FETCH emp_cursor INTO v_empno,v_name,v_job;
       EXIT WHEN emp_cursor%NOTFOUND;
  END LOOP;
  IF emp_cursor%ISOPEN THEN
    DBMS_OUTPUT.PUT_LINE('遊標已打開');
    DBMS_OUTPUT.PUT_LINE('讀取了'||emp_cursor%ROWCOUNT||'');
  ELSE
    DBMS_OUTPUT.PUT_LINE('遊標沒有打開');
  END IF;  
  CLOSE emp_cursor;
END;

經過%ISOPEN屬性判斷遊標是否打開,%ROWCOUNT判斷獲取行數。

二、隱式遊標:由系統定義併爲它建立工做區域,而且隱式的定義打開提取關閉,隱式遊標的遊標名就是'SQL',屬性和顯示遊標相同,主要用於對單行select語句或dml操做進行處理。

Example:又用戶輸入員工號修改員工工資如成功則打印輸出成功標誌。

爲了儘可能不改變原表,建立新表emp_new和原表數據相同:

CREATE TABLE emp_new
AS
SELECT * FROM emp;
BEGIN
  UPDATE emp_new SET sal = sal+500 WHERE empno=&empno;
  IF SQL%FOUND THEN
    DBMS_OUTPUT.PUT_LINE('成功修改');
    COMMIT;
  ELSE
    DBMS_OUTPUT.PUT_LINE('修改失敗');
    ROLLBACK;
  END IF;
END;

這裏注意增刪改之後要對作的操做進行commit提交,若是操做失敗則rollback回滾剛纔的操做。

三、參數遊標:

在定義遊標時加入參數的遊標,能夠配合遊標for循環快速找到須要的數據。這裏先講一下游標for循環

A、遊標FOR循環:

隱含的執行了打開提取關閉數據,代碼精簡不少。Expression:

FOR table_record IN table_cursor LOOP

  STATEMENT;

END LOOP;

 Example:使用遊標For循環打印輸出員工信息:

DECLARE
CURSOR emp_cursor IS SELECT empno,ename,job FROM emp;
BEGIN
  FOR emp_record IN emp_cursor LOOP
    DBMS_OUTPUT.PUT_LINE('員工號:'||emp_record.empno||'員工姓名'||emp_record.ename||'員工職位'||emp_record.job);
  END LOOP;
END;

這裏遊標FOR循環省去了對於取到的數據的變量的命名和賦值,同時若是所有打印則不用寫循環條件,代碼精簡了不少。

若是想讓代碼更加精簡,則能夠去掉對遊標的聲明引入子查詢便可,操做以下。

BEGIN
  FOR emp_record IN (SELECT empno,ename,job FROM emp) LOOP
    DBMS_OUTPUT.PUT_LINE('員工號:'||emp_record.empno||'員工姓名'||emp_record.ename||'員工職位'||emp_record.job);
  END LOOP;
END;

代碼更加精簡,獲得的結果相同。和隱式遊標是否是有點像,但隱式遊標主要用於的是單行select和dml語句的操做,注意2者用法的區別。

下面繼續參數遊標的實例:

Example:輸入部門號打印員工信息:

DECLARE
CURSOR emp_cursor(dno NUMBER)IS SELECT empno,ename,job FROM emp WHERE deptno=dno;
BEGIN
  FOR emp_record IN emp_cursor(&dno) LOOP
    DBMS_OUTPUT.PUT_LINE('員工號'||emp_record.empno||'姓名'||emp_record.ename||'職位'||emp_record.job);
  END LOOP;
END;

 

 

這裏既然有參數,那麼必然會有對遊標的聲明,在結合遊標FOR循環快速超找所須要的數據。

3、使用遊標修改數據的注意事項

一、使用遊標修改數據時,爲防止他人在本身操做數據時對數據進行修改,oracle提供for update子句進行加鎖。

同時在你使用update或delete時,必須使用where current of+name_cursor語句,以及在最後記得提交。若是

是級聯操做則可使用for update of 來進行相關表的加鎖。

Example1:對職位是PRESIDENT的員工加1000工資,MANAGER的人加500工資

CREATE TABLE emp_new
AS
SELECT * FROM emp;
DECLARE
CURSOR empnew_cursor IS SELECT ename,job FROM emp_new FOR UPDATE;
BEGIN
  FOR empnew_record IN empnew_cursor LOOP
    DBMS_OUTPUT.PUT_LINE('姓名'||empnew_record.ename||'職位'||empnew_record.job);
    IF empnew_record.job='PRESIDENT' THEN
      UPDATE emp_new SET sal=sal+1000 WHERE CURRENT OF empnew_cursor;
    ELSIF empnew_record.job='MANAGER' THEN
      UPDATE emp_new SET sal=sal+500 WHERE CURRENT OF empnew_cursor;
    END IF;
  END LOOP;
  COMMIT;
END;
SELECT * FROM EMP WHERE job in('PRESIDENT','MANAGER');
SELECT * FROM EMP_NEW WHERE job in('PRESIDENT','MANAGER');

能夠看到這裏工資有了相應的變化。

 

 

至此,Oracle遊標解析完畢,總而言之,遊標只是做爲咱們從數據庫中提取出來的一部分數據,咱們針對這個結果集作一系列的操做。

                                            2018-09-07    16:15:34

相關文章
相關標籤/搜索