PL/SQL Step By Step(二)

    遊標是PL/SQL很是重要的一部分,也是不少人爲何使用PL/SQL的緣由。遊標可以讓開發者對數據庫查詢進行記錄級別的控制。也就是說,能夠對查詢返回的數據一次一行進行步進,而且在兩行之間停頓一段時間來進行一些特別的處理操做。sql

    遊標分爲兩種:隱式遊標和顯式遊標。下面咱們先介紹隱式遊標,一會在介紹更增強大的顯示遊標。數據庫

    1.隱式遊標函數

    隱式遊標是不須要定義的,說白了,隱式遊標就是數據操做語言DML,例如SELECT語句。也就是咱們上一講中提到的PL/SQL處理部分中的語句。先看一個例子:ui

DECLARE
  v_port_name varchar2(80);
BEGIN;
  SELECT PORT_NAME 
  INTO v_port_name
  FROM PORTS
  WHERE PORT_ID = 100;
  DBMS_OUTPUT.PUT_LINE(v_port_name);
END;

    上面的這個SELECT語句就是一個隱式遊標的例子。須要注意的是INTO關鍵字,基於SELECT語句的隱式遊標必須使用INTO關鍵字用一系列變量來取得查詢出來的各列的值。spa

    隱式遊標從本質上來講就是嵌在PL/SQL中的SQL語句,只要是合法的SQL語句就行。這不侷限於SELECT語句,還可使DELETE,INSERT,UPDATE語句,甚至包括DECODE語句。咱們前面提到,DECODE是惟一一個不能做爲PL/SQL表達式的SQL函數,可是它依然是合法的SQL語句,所以嵌入PL/SQL也能夠構成隱式遊標,這一點須要注意。code

    須要特別提一下:在隱式遊標中定義的SELECT語句必須且只能返回一條記錄,不然的話,Oracle會報錯。這一點也很是重要。有人對這一點很困惑,但其實道理仍是比較簡單的:前面咱們說了,基於SELECT語句的隱式遊標必須使用INTO將查詢到的結果的每一列以此存進定義的變量。你們都知道,變量一次只能處理一個值,因此隱式遊標SELECT只容許返回一條記錄。內存

    若是SELECT返回的記錄超過一條,那麼換成咱們下面要講的顯式遊標吧。開發

    2.顯式遊標博客

    顯式遊標是在PL/SQL生命部分定義,而且在處理部分使用的遊標。他之因此叫顯式遊標是由於他在定義的的時候須要命名。在使用顯式遊標的時候,主要須要和四個關鍵詞打交道,咱們逐一講解:class

CURSOR
這個關鍵字用在PL/SQL聲明部分,用來定義顯示遊標,其格式以下:
CURSOR cursor_name IS a_valid_select_statement

OPEN
這個關鍵詞用在PL/SQL處理部分,用來解析顯式遊標中定義的SQL語句,而且爲執行作準備

FETCH...INTO
這個關鍵詞用來一次獲取顯式遊標查詢結果的一行記錄,而且將每一行記錄的各個字段
分別賦值給一系列變量。其格式爲:
FETCH cursor_name INTO val1,...valn

CLOSE
關閉遊標,這樣PL/SQL解析程序能夠釋放內存。可是即便不寫CLOSE語句,PL/SQL解析程序
最終仍是會發現並釋放顯式遊標佔用的內存。

    說了這麼多,咱們看一個綜合使用了隱式遊標和顯示有標的例子:

DECLARE
  v_today DATE;
  --定義顯式遊標開始
  CURSOR cur_cruises IS
    SELECT C.CAPTAIN_ID,
           E.LAST_NAME || ',' || E.FIRST_NAME FULL_NAME
    FROM CRUISES C,
         EMPLOYEES E
    WHERE C.CAPTAIN_ID = E.EMPLOYEE_ID;
      AND E.START_DATE >= v_today
      AND E.END_DATE <= v_today;
    
  --定義顯式遊標結束
  
  v_captain_id NUMBER(3);
  v_full_name VARCHAR2(40);
BEGIN
  --使用隱式遊標開始
  SELECT TRUNC(SYSDATE)
  INTO v_today
  FROM DUAL;
  --使用隱式遊標結束
  
  OPEN cur_cruises; --打開遊標
  
  LOOP
    FETCH cur_cruises INTO v_captain_id,v_full_name;--獲取數據
    
    EXIT WHEN cur_cruises%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE('Captain ID:' || v_captain_id);
    DBMS_OUTPUT.PUT_LINE('Name      :' || v_full_name);
  END LOOP;
  CLOSE cur_cruises;--關閉遊標
  
END;

    這段代碼的意圖是很是顯而易見的,必要的註釋在代碼中體現了。顯式遊標能夠經過任何可獨立運行的SQL語句來構建,除此以外,在顯式遊標的定義中可使用以前定義的變量,上面的代碼就是一個很好的例子。

    3.遊標的屬性

    上面的代碼中出現了一個陌生的東西:%NOTFOUND。這是一種遊標的屬性。接下來,咱們分別介紹遊標的集中屬性:

NOTFOUND
是一個BOOLEAN類型。當最近一次FETCH操做沒有返回記錄時,該屬性值爲真,不然爲假。
FOUND
是一個BOOLEAN類型。當最近一次FETCH操做返回記錄時,該屬性值爲真,不然爲假。
ISOPEN
是一個BOOLEAN類型。判斷遊標是否已經打開。
ROWCOUNT
遊標目前爲止已經處理過的行數。

    上面的屬性對於隱式遊標和顯示遊標都是存在的。可是有一個問題,隱式遊標是沒有名字的,沒辦法向上面例子代碼中顯示遊標同樣使用後屬性。能夠經過下面這種方式:

BEGIN
  UPDATE EMPLOYEES
  SET SALARY = SALARY * 1.5;--加薪啦
  DBMS_OUTPUT.PUT_LINE('Rows Affacted:' || SQL%ROWCOUNT);
END;

經過使用SQL來引用最近的一個隱式遊標。

    4.循環語句回顧

    上一篇博客中,咱們介紹了PL/SQL循環語句的四種形式,而且提到了CURSOR循環。可是當時沒介紹遊標,因此沒有詳細講解。如今有了遊標的知識,咱們來看看CURSOR循環究竟是個什麼東東。看一個例子:

BEGIN
  FOR rec_employee IN (SELECT EMPLOYEE_ID FROM EMPLOYEES)
  LOOP
    DBMS_OUTPUT.PUT_LINE('IN THE FOR LOOP' || rec_employee.EMPLOYEE_ID);
  END LOOP;
END;

    這種循環其實基本上和以前的數值FOR循環同樣,只不過數值FOR循環經過一個計數變量來迭代,而這裏順着遊標記錄一條一條往下從而達到迭代效果。實際上,CURSOR FOR循環自動作了四件事情:

  1. 將rec_employee定義爲%ROWTYPE類型。
  2. 定義了一個匿名的顯示遊標
  3. 自動從頭至尾遍歷查詢出的記錄
  4. 離開循環,執行CLOSE操做,關閉遊標。

    5.補充

    上面提到了%ROWTYPE類型定義,這裏補充一下PL/SQL中的兩種高級的變量類型定義方法:%TYPE和%ROWTYPE。

    %TYPE:將變量定義爲%TYPE左邊的東西同樣,例如:

DECLARE
  v_name SOMETABLE.USERNAME%TYPE;--將v_name變量定義爲和SOMETABLE表的USERNAME字段同樣的類型
BEGIN
  --DO STH
END;

    %ROWTYPE:將變量定義爲和左邊東西一行同樣的類型(也就是全部字段類型一一對應),上面的rec_employee 就是個例子。

    這一講就到這裏,遊標是PL/SQL中很是重要的語言特性和組成部分,須要重點掌握。

相關文章
相關標籤/搜索