遊標的詳細用法
引用:https://www.cnblogs.com/xiaoliu66007/p/7495753.html
遊標的概念:
遊標是SQL的一個記憶體工作區,由系統或使用者以變數的形式定義。遊標的作用就是用於臨時儲存從資料庫中提取的資料塊。在某些情況下,需要把資料從存放在磁碟的表中調到計算機記憶體中進行處理,最後將處理結果顯示出來或最終寫回資料庫。這樣資料處理的速度才會提高,否則頻繁的磁碟資料交換會降低效率。遊標有兩種型別:顯式遊標和隱式遊標。在前述程式中用到的SELECT...INTO...查詢語句,一次只能從資料庫中提取一行資料,對於這種形式的查詢和DML操作,系統都會使用一個隱式遊標。但是如果要提取多行資料,就要由程式設計師定義一個顯式遊標,並通過與遊標有關的語句進行處理。顯式遊標對應一個返回結果為多行多列的SELECT語句。
遊標一旦開啟,資料就從資料庫中傳送到遊標變數中,然後應用程式再從遊標變數中分解出需要的資料,並進行處理。
隱式遊標
如前所述,DML操作和單行SELECT語句會使用隱式遊標,它們是:
* 插入操作:INSERT。
* 更新操作:UPDATE。
* 刪除操作:DELETE。
* 單行查詢操作:SELECT ... INTO ...。
當系統使用一個隱式遊標時,可以通過隱式遊標的屬性來了解操作的狀態和結果,進而控制程式的流程。隱式遊標可以使用名字SQL來訪問,但要注意,通過SQL遊標名總是隻能訪問前一個DML操作或單行SELECT操作的遊標屬性。所以通常在剛剛執行完操作之後,立即使用SQL遊標名來訪問屬性。遊標的屬性有四種,如下所示。 Sql程式碼
- 隱式遊標的屬性 返回值型別 意 義
- SQL%ROWCOUNT 整型 代表DML語句成功執行的資料行數
- SQL%FOUND 布林型 值為TRUE代表插入、刪除、更新或單行查詢操作成功
- SQL%NOTFOUND 布林型 與SQL%FOUND屬性返回值相反
- SQL%ISOPEN 布林型 DML執行過程中為真,結束後為假
【訓練1】 使用隱式遊標的屬性,判斷對僱員工資的修改是否成功。
步驟1:輸入和執行以下程式:
- SET SERVEROUTPUT ON
- BEGIN
- UPDATE emp SET sal=sal+100 WHERE empno=1234;
- IF SQL%FOUND THEN
- DBMS_OUTPUT.PUT_LINE('成功修改僱員工資!');
- COMMIT;
- ELSE
- DBMS_OUTPUT.PUT_LINE('修改僱員工資失敗!');
- END IF;
- END;
執行結果為:
- 修改僱員工資失敗!
- PL/SQL 過程已成功完成。
步驟2:將僱員編號1234改為7788,重新執行以上程式:
執行結果為:
- 成功修改僱員工資!
- PL/SQL 過程已成功完成。
說明:本例中,通過SQL%FOUND屬性判斷修改是否成功,並給出相應資訊。
顯式遊標
遊標的定義和操作
遊標的使用分成以下4個步驟。
1.宣告遊標
在DECLEAR部分按以下格式宣告遊標:
CURSOR 遊標名[(引數1 資料型別[,引數2 資料型別...])]
IS SELECT語句;
引數是可選部分,所定義的引數可以出現在SELECT語句的WHERE子句中。如果定義了引數,則必須在開啟遊標時傳遞相應的實際引數。
SELECT語句是對錶或檢視的查詢語句,甚至也可以是聯合查詢。可以帶WHERE條件、ORDER BY或GROUP BY等子句,但不能使用INTO子句。在SELECT語句中可以使用在定義遊標之前定義的變數。
2.開啟遊標
在可執行部分,按以下格式開啟遊標:
OPEN 遊標名[(實際引數1[,實際引數2...])];
開啟遊標時,SELECT語句的查詢結果就被傳送到了遊標工作區。
3.提取資料
在可執行部分,按以下格式將遊標工作區中的資料取到變數中。提取操作必須在開啟遊標之後進行。
FETCH 遊標名 INTO 變數名1[,變數名2...];
或
FETCH 遊標名 INTO 記錄變數;
遊標開啟後有一個指標指向資料區,FETCH語句一次返回指標所指的一行資料,要返回多行需重複執行,可以使用迴圈語句來實現。控制迴圈可以通過判斷遊標的屬性來進行。
下面對這兩種格式進行說明:
第一種格式中的變數名是用來從遊標中接收資料的變數,需要事先定義。變數的個數和型別應與SELECT語句中的欄位變數的個數和型別一致。
第二種格式一次將一行資料取到記錄變數中,需要使用%ROWTYPE事先定義記錄變數,這種形式使用起來比較方便,不必分別定義和使用多個變數。
定義記錄變數的方法如下:
變數名 表名|遊標名%ROWTYPE;
其中的表必須存在,遊標名也必須先定義。
4.關閉遊標
CLOSE 遊標名;
顯式遊標開啟後,必須顯式地關閉。遊標一旦關閉,遊標佔用的資源就被釋放,遊標變成無效,必須重新開啟才能使用。
以下是使用顯式遊標的一個簡單練習。
【訓練1】 用遊標提取emp表中7788僱員的名稱和職務。
- SET SERVEROUTPUT ON
- DECLARE
- v_ename VARCHAR2(10);
- v_job VARCHAR2(10);
- CURSOR emp_cursor IS
- SELECT ename,job FROM emp WHERE empno=7788;
- BEGIN
- OPEN emp_cursor;
- FETCH emp_cursor INTO v_ename,v_job;
- DBMS_OUTPUT.PUT_LINE(v_ename||','||v_job);
- CLOSE emp_cursor;
- END;
執行結果為:
- SCOTT,ANALYST
- PL/SQL 過程已成功完成。
說明:該程式通過定義遊標emp_cursor,提取並顯示僱員7788的名稱和職務。
作為對以上例子的改進,在以下訓練中採用了記錄變數。
【訓練2】 用遊標提取emp表中7788僱員的姓名、職務和工資。
- SET SERVEROUTPUT ON
- DECLARE
- CURSOR emp_cursor IS SELECT ename,job,sal FROM emp WHERE empno=7788;
- emp_record emp_cursor%ROWTYPE;
- BEGIN
- OPEN emp_cursor;
- FETCH emp_cursor INTO emp_record;
- DBMS_OUTPUT.PUT_LINE(emp_record.ename||','|| emp_record.job||','|| emp_record.sal);
- CLOSE emp_cursor;
- END;
執行結果為:
- SCOTT,ANALYST,3000
- PL/SQL 過程已成功完成。
說明:例項中使用記錄變數來接收資料,記錄變數由遊標變數定義,需要出現在遊標定義之後。
注意:可通過以下形式獲得記錄變數的內容:
記錄變數名.欄位名。
【訓練3】 顯示工資最高的前3名僱員的名稱和工資。
- SET SERVEROUTPUT ON
- DECLARE
- V_ename VARCHAR2(10);
- V_sal NUMBER(5);
- CURSOR emp_cursor IS SELECT ename,sal FROM emp ORDER BY sal DESC;
- BEGIN
- OPEN emp_cursor;
- FOR I IN 1..3 LOOP
- FETCH emp_cursor INTO v_ename,v_sal;
- DBMS_OUTPUT.PUT_LINE(v_ename||','||v_sal);
- END LOOP;
- CLOSE emp_cursor;
- END;
執行結果為:
- KING,5000
- SCOTT,3000
- FORD,3000
- PL/SQL 過程已成功完成。
說明:該程式在遊標定義中使用了ORDER BY子句進行排序,並使用迴圈語句來提取多行資料。
遊標迴圈
【訓練1】 使用特殊的FOR迴圈形式顯示全部僱員的編號和名稱。
- SET SERVEROUTPUT ON
- DECLARE
- CURSOR emp_cursor IS
- SELECT empno, ename FROM emp;
- BEGIN
- FOR Emp_record IN emp_cursor LOOP
- DBMS_OUTPUT.PUT_LINE(Emp_record.empno|| Emp_record.ename);
- END LOOP;
- END;
執行結果為:
- 7369SMITH
- 7499ALLEN
- 7521WARD
- 7566JONES
- PL/SQL 過程已成功完成。
說明:可以看到該迴圈形式非常簡單,隱含了記錄變數的定義、遊標的開啟、提取和關閉過程。Emp_record為隱含定義的記錄變數,迴圈的執行次數與遊標取得的資料的行數相一致。
【訓練2】 另一種形式的遊標迴圈。
- SET SERVEROUTPUT ON
- BEGIN
- FOR re IN (SELECT ename FROM EMP) LOOP
- DBMS_OUTPUT.PUT_LINE(re.ename)
- END LOOP;
- END;
執行結果為:
- SMITH
- ALLEN
- WARD
- JONES
說明:該種形式更為簡單,省略了遊標的定義,遊標的SELECT查詢語句在迴圈中直接出現。
顯式遊標屬性
雖然可以使用前面的形式獲得遊標資料,但是在遊標定義以後使用它的一些屬性來進行結構控制是一種更為靈活的方法。顯式遊標的屬性如下所示。
- 遊標的屬性 返回值型別 意 義
- %ROWCOUNT 整型 獲得FETCH語句返回的資料行數
- %FOUND 布林型 最近的FETCH語句返回一行資料則為真,否則為假
- %NOTFOUND 布林型 與%FOUND屬性返回值相反
- %ISOPEN 布林型 遊標已經開啟時值為真,否則為假
可按照以下形式取得遊標的屬性:
遊標名%屬性
要判斷遊標emp_cursor是否處於開啟狀態,可以使用屬性emp_cursor%ISOPEN。如果遊標已經開啟,則返回值為“真”,否則為“假”。具體可參照以下的訓練。
【訓練1】 使用遊標的屬性練習。