--===============================
-- PL/SQL --> 隱式游標(biāo) (SQL%FOUND)
--===============================
?
??? 在 PL / SQL 中,游標(biāo)的使用分為兩種,一種是顯示游標(biāo),一種是隱式游標(biāo),顯示游標(biāo)的使用需要事先使用 declare 來(lái)進(jìn)行聲明,其過(guò)程包括
聲明游標(biāo),打開游標(biāo),從游標(biāo)提取數(shù)據(jù),關(guān)閉游標(biāo)。該方式多用于處理 select 語(yǔ)句返回的多行數(shù)據(jù)的情形。而隱式游標(biāo)則由則由系統(tǒng)自動(dòng)定義
,當(dāng) DML 被使用時(shí), Oracle 為每一個(gè)不屬于顯示游標(biāo)的 DML 語(yǔ)句都創(chuàng)建一個(gè)隱式游標(biāo),其聲明、打開、關(guān)閉都是系統(tǒng)自動(dòng)進(jìn)行。多用于配合 DML
返回單行數(shù)據(jù)的處理。
??? 有關(guān)顯示游標(biāo)的使用,請(qǐng)參考: PL/SQL --> 游 標(biāo)
???
一、隱式游標(biāo)的定義及其屬性
??? 定義
??????? 隱式游標(biāo)則由則由系統(tǒng)自動(dòng)定義,非顯示定義游標(biāo)的 DML 語(yǔ)句即被賦予隱式游標(biāo)屬性。其過(guò)程由 oracle 控制,完全自動(dòng)化。隱式游標(biāo)
??????? 的名稱是 SQL ,不能對(duì) SQL 游標(biāo)顯式地執(zhí)行 OPEN , FETCH , CLOSE 語(yǔ)句。
??? 屬性
??????? 類似于顯示游標(biāo),隱式游標(biāo)同樣具有四種屬性,只不過(guò)隱式游標(biāo)以 SQL % 開頭,而顯示游標(biāo)以 Cursor_name % 開頭
??????? 通過(guò) SQL % 總是只能訪問(wèn)前一個(gè) DML 操作或單行 SELECT 操作的游標(biāo)屬性,用于判斷 DML 執(zhí)行的狀態(tài)和結(jié)果,進(jìn)而控制程序的流程
???????
??????? SQL % ISOPEN ???
??????????? 游標(biāo)是否打開。當(dāng)執(zhí)行 select into , insert update , delete 時(shí), Oracle 會(huì)隱含地打開游標(biāo),且在該語(yǔ)句執(zhí)行完畢或隱含地關(guān)閉
??????????? 游標(biāo),因?yàn)槭请[式游標(biāo),故 SQL % ISOPEN 總是 false ??
???????????
??????? SQL % FOUND ??????
??????????? 判斷 SQL 語(yǔ)句是否成功執(zhí)行。當(dāng)有作用行時(shí)則成功執(zhí)行為 true ,否則為 false 。
???????????????????
??????? SQL % NOTFOUND ???
??????????? 判斷 SQL 語(yǔ)句是否成功執(zhí)行。當(dāng)有作用行時(shí)否其值為 false ,否則其值為 true 。
???????????
??????? SQL % ROWCOUNT ??
??????????? 在執(zhí)行任何 DML 語(yǔ)句之前, SQL % ROWCOUNT 的值都是 NULL, 對(duì)于 SELECT INTO 語(yǔ)句,如果執(zhí)行成功, SQL % ROWCOUNT 的值為 , 如果沒(méi)有
??????????? 成功, SQL % ROWCOUNT 的值為,同時(shí)產(chǎn)生一個(gè)異常 NO_DATA_FOUND 。
???????
二、演示
??? 1.SQL % FOUND 的使用
??????? DECLARE
??????? ? v_empno emp . empno % TYPE :=& no ;
??????? BEGIN
??????? ? UPDATE emp SET sal = sal + 200 ???? -- 根據(jù)給定的 empno ,更新一條記錄
??????? ? WHERE empno = v_empno ;
??????? ? IF SQL % FOUND THEN ????????????? -- 使用 SQL 游標(biāo)屬性 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 游標(biāo)的綜合應(yīng)用 ( 根據(jù) SQL 游標(biāo)的不同屬性返回不同的結(jié)果 )
??????? 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 ?? -- 下面是成功更新后的結(jié)果
??????? 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 ?? -- 下面是未成功更新后的結(jié)果
??????? 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 時(shí),隱式游標(biāo)的使用
??????? SELECT INTO 用于將單行結(jié)果集放置到變量之中。
??????? SELECT INTO 處理的結(jié)果包括兩種種情況
??????????? 查詢結(jié)果返回單行, SELECT INTO 被成功執(zhí)行
??????????? 查詢結(jié)果沒(méi)有返回行, PL / SQL 將拋出 no_data_found 異常
??????????? 查詢結(jié)果返回多行, PL / SQL 將拋出 too_many_rows 異常
??????? 對(duì)于上述兩種異常發(fā)生時(shí),類似于普通異常處理,程序控制權(quán)轉(zhuǎn)移到異常處理部分 ( 如沒(méi)有異常處理則程序中斷 ) 。對(duì)于異常被激后發(fā)
??????? , SQL 游標(biāo)的四個(gè)屬性在此將不可使用,如下面的例子:
??????????? 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
???????????
??????? 從上面的演示中可以看到,當(dāng) select into 沒(méi)有返回行時(shí), IF ? SQL % ROWCOUNT = 0 OR SQL % NOTFOUND THEN 語(yǔ)句并沒(méi)有被執(zhí)行。
??????? 使用下面改進(jìn)過(guò)的代碼來(lái)執(zhí)行,即可以將 SQL 游標(biāo)屬性判斷放置到 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
???????????
??????? 更多關(guān)于隱式游標(biāo)的探討,請(qǐng)參考: IMPLICIT CURSOR ATTRIBUTE SQL%NOTFOUND NOT WORKING ?
??????? ???????
三、更多參考
有關(guān) SQL 請(qǐng)參考
??????? SQL 基礎(chǔ)--> 子查詢
??????? SQL 基礎(chǔ)--> 多表查詢
SQL 基礎(chǔ)--> ROLLUP 與CUBE 運(yùn)算符實(shí)現(xiàn)數(shù)據(jù)匯總
SQL 基礎(chǔ)--> 層次化查詢(START BY ... CONNECT BY PRIOR)
?
??? 有關(guān) PL/SQL 請(qǐng)參考
??????? PL/SQL --> 語(yǔ)言基礎(chǔ)
PL/SQL --> 隱式游標(biāo)(SQL%FOUND)
?
?
???????
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元

