遊標是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循環自動作了四件事情:
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中很是重要的語言特性和組成部分,須要重點掌握。