--===============================
-- PL/SQL --> 隱式游標 (SQL%FOUND)
--===============================
?
??? 在 PL / SQL 中,游標的使用分為兩種,一種是顯示游標,一種是隱式游標,顯示游標的使用需要事先使用 declare 來進行聲明,其過程包括
聲明游標,打開游標,從游標提取數據,關閉游標。該方式多用于處理 select 語句返回的多行數據的情形。而隱式游標則由則由系統自動定義
,當 DML 被使用時, Oracle 為每一個不屬于顯示游標的 DML 語句都創建一個隱式游標,其聲明、打開、關閉都是系統自動進行。多用于配合 DML
返回單行數據的處理。
??? 有關顯示游標的使用,請參考: PL/SQL --> 游 標
???
一、隱式游標的定義及其屬性
??? 定義
??????? 隱式游標則由則由系統自動定義,非顯示定義游標的 DML 語句即被賦予隱式游標屬性。其過程由 oracle 控制,完全自動化。隱式游標
??????? 的名稱是 SQL ,不能對 SQL 游標顯式地執行 OPEN , FETCH , CLOSE 語句。
??? 屬性
??????? 類似于顯示游標,隱式游標同樣具有四種屬性,只不過隱式游標以 SQL % 開頭,而顯示游標以 Cursor_name % 開頭
??????? 通過 SQL % 總是只能訪問前一個 DML 操作或單行 SELECT 操作的游標屬性,用于判斷 DML 執行的狀態和結果,進而控制程序的流程
???????
??????? SQL % ISOPEN ???
??????????? 游標是否打開。當執行 select into , insert update , delete 時, Oracle 會隱含地打開游標,且在該語句執行完畢或隱含地關閉
??????????? 游標,因為是隱式游標,故 SQL % ISOPEN 總是 false ??
???????????
??????? SQL % FOUND ??????
??????????? 判斷 SQL 語句是否成功執行。當有作用行時則成功執行為 true ,否則為 false 。
???????????????????
??????? SQL % NOTFOUND ???
??????????? 判斷 SQL 語句是否成功執行。當有作用行時否其值為 false ,否則其值為 true 。
???????????
??????? SQL % ROWCOUNT ??
??????????? 在執行任何 DML 語句之前, SQL % ROWCOUNT 的值都是 NULL, 對于 SELECT INTO 語句,如果執行成功, SQL % ROWCOUNT 的值為 , 如果沒有
??????????? 成功, SQL % ROWCOUNT 的值為,同時產生一個異常 NO_DATA_FOUND 。
???????
二、演示
??? 1.SQL % FOUND 的使用
??????? DECLARE
??????? ? v_empno emp . empno % TYPE :=& no ;
??????? BEGIN
??????? ? UPDATE emp SET sal = sal + 200 ???? -- 根據給定的 empno ,更新一條記錄
??????? ? WHERE empno = v_empno ;
??????? ? IF SQL % FOUND THEN ????????????? -- 使用 SQL 游標屬性 SQL%FOUND 作為判斷條件
??????????? COMMIT ;
??????????? DBMS_OUTPUT . PUT_LINE ( 'SQL code is executed successful' );
??????? ? ELSE
??????????? DBMS_OUTPUT . PUT_LINE ( 'The Employee is not exist' );
??????????? ROLLBACK ;
??????? ? END IF ;
??????? END ;
?
??????? Enter value for no : 7788
??????? old ?? 2 : ?? v_empno emp . empno % TYPE :=& no ;
??????? new ?? 2 : ?? v_empno emp . empno % TYPE := 7788 ;
??????? SQL code is executed successful
?
??????? PL / SQL procedure successfully completed
???
??? 2.SQL 游標的綜合應用 ( 根據 SQL 游標的不同屬性返回不同的結果 )
??????? DECLARE
??????? ? v_dept emp . deptno % TYPE := & no ;
?
??????? BEGIN
?
??????? ? IF SQL % ROWCOUNT >= 0 THEN ? -- 判斷更新前 SQL%ROWCOUNT 的屬性
??????????? DBMS_OUTPUT . PUT_LINE ( 'SQL%ROWCOUNT value is ' || SQL % ROWCOUNT ||
??????????????????????????????? ? 'before updated' );
??????? ? ELSE
??????????? DBMS_OUTPUT . PUT_LINE ( 'SQL%ROWCOUNT value is NULL before updated' );
??????? ? END IF ;
?
??????? ? UPDATE emp SET sal = sal + 200 WHERE deptno = v_dept ;
?
??????? ? IF SQL % FOUND THEN ??? -- 判斷 SQL%FOUND 的屬性
??????????? DBMS_OUTPUT . PUT_LINE ( 'SQL code is executed successful' );
??????????? DBMS_OUTPUT . PUT_LINE ( 'SQL%Found is TRUE' );
??????? ? ELSE
??????????? DBMS_OUTPUT . PUT_LINE ( 'No such department' );
??????????? DBMS_OUTPUT . PUT_LINE ( 'SQL%Found is FALSE' );
??????? ? END IF ;
?
??????? ? IF SQL % NOTFOUND THEN ??? -- 判斷 SQL%NOTFOUND 的屬性
??????????? DBMS_OUTPUT . PUT_LINE ( 'SQL%NotFound is TRUE' );
??????? ? ELSE
??????????? DBMS_OUTPUT . PUT_LINE ( 'SQL%NotFound is FALSE' );
??????? ? END IF ;
?
??????? ? IF SQL % ISOPEN THEN ??? -- 判斷 SQL%ISOPEN 的屬性
??????????? DBMS_OUTPUT . PUT_LINE ( 'SQL%ISOPEN is TRUE' );
??????? ? ELSE
??????????? DBMS_OUTPUT . PUT_LINE ( 'SQL%ISOPEN is FALSE' );
??????? ? END IF ;
?
??????? ? DBMS_OUTPUT . PUT_LINE ( 'The rows updated is :' || SQL % ROWCOUNT ||
??????????????????????????? ?? ' rows by SQL Cursor' ); -- 判斷 SQL%ROWCOUNT 的屬性
??????? END ;
???????
??????? Enter value for no : 10 ?? -- 下面是成功更新后的結果
??????? SQL % ROWCOUNT value is NULL before updated
??????? SQL code is executed successful
??????? SQL % Found is TRUE
??????? SQL % NotFound is FALSE
??????? SQL % ISOPEN is FALSE
??????? The rows updated is : 3 rows by SQL Cursor
???????
??????? Enter value for no : 80 ?? -- 下面是未成功更新后的結果
??????? SQL % ROWCOUNT value is NULL before updated
??????? No such department
??????? SQL % Found is FALSE
??????? SQL % NotFound is TRUE
??????? SQL % ISOPEN is FALSE
??????? The rows updated is : 0 rows by SQL Cursor ??
???????
??? 3. SELECT INTO 時,隱式游標的使用
??????? SELECT INTO 用于將單行結果集放置到變量之中。
??????? SELECT INTO 處理的結果包括兩種種情況
??????????? 查詢結果返回單行, SELECT INTO 被成功執行
??????????? 查詢結果沒有返回行, PL / SQL 將拋出 no_data_found 異常
??????????? 查詢結果返回多行, PL / SQL 將拋出 too_many_rows 異常
??????? 對于上述兩種異常發生時,類似于普通異常處理,程序控制權轉移到異常處理部分 ( 如沒有異常處理則程序中斷 ) 。對于異常被激后發
??????? , SQL 游標的四個屬性在此將不可使用,如下面的例子:
??????????? DECLARE
??????????? ? v_ename emp . ename % TYPE ;
??????????? ?
??????????? BEGIN
??????????? ? SELECT ename INTO v_ename FROM emp WHERE empno =& no ;
??????????? ? IF ? SQL % ROWCOUNT = 0 OR SQL % NOTFOUND THEN
??????????????? DBMS_OUTPUT . PUT_LINE ( 'The record ' ||& no|| ' is not exist!' );
??????????? ? ELSE
??????????????? DBMS_OUTPUT . PUT_LINE ( 'The name for record ' ||& no|| ' is ' || v_ename );
??????????? ? END IF ;
?
??????????? EXCEPTION ?
??????????? ? WHEN NO_DATA_FOUND THEN
??????????????? DBMS_OUTPUT . PUT_LINE ( 'No data found for ' ||& no );
??????????? ??
??????????? END ; ???????
???????????
??????????? Enter value for no : 70
??????????? No data found for 70
???????????
??????????? Enter value for no : 7788
??????????? The name for record 7788 is SCOTT
???????????
??????? 從上面的演示中可以看到,當 select into 沒有返回行時, IF ? SQL % ROWCOUNT = 0 OR SQL % NOTFOUND THEN 語句并沒有被執行。
??????? 使用下面改進過的代碼來執行,即可以將 SQL 游標屬性判斷放置到 EXCEPTION 部分
??????????? DECLARE
??????????? ? v_ename emp . ename % TYPE ;
??????????? ?
??????????? BEGIN
??????????? ? SELECT ename INTO v_ename FROM emp WHERE empno =& no ;
??????????? ? IF SQL % NOTFOUND THEN
??????????????? DBMS_OUTPUT . PUT_LINE ( 'The record ' ||& no|| ' is not exist!' );
??????????? ? ELSE
??????????????? DBMS_OUTPUT . PUT_LINE ( 'The name for record ' ||& no|| ' is ' || v_ename );
??????????? ? END IF ;
?
??????????? EXCEPTION ?
??????????? ? WHEN NO_DATA_FOUND THEN
??????????????? IF SQL % NOTFOUND THEN
??????????????? ? DBMS_OUTPUT . PUT_LINE ( 'The record ' ||& no|| ' is not exist!' );
??????????????? ? DBMS_OUTPUT . PUT_LINE ( 'No data found for ' ||& no );
??????????????? ELSE
??????????????? ? DBMS_OUTPUT . PUT_LINE ( 'The name for record ' ||& no|| ' is ' || v_ename );
??????????????? END IF ;
??????????? ??
??????????? END ;
???????????
??????????? Enter value for no : 80
??????????? The record 80 is not exist !
??????????? No data found for 80
???????????
??????? 更多關于隱式游標的探討,請參考: IMPLICIT CURSOR ATTRIBUTE SQL%NOTFOUND NOT WORKING ?
??????? ???????
三、更多參考
有關 SQL 請參考
??????? SQL 基礎--> 子查詢
??????? SQL 基礎--> 多表查詢
SQL 基礎--> ROLLUP 與CUBE 運算符實現數據匯總
SQL 基礎--> 層次化查詢(START BY ... CONNECT BY PRIOR)
?
??? 有關 PL/SQL 請參考
??????? PL/SQL --> 語言基礎
?
?
???????
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
