一、游標(biāo)
游標(biāo)用來(lái)處理從數(shù)據(jù)庫(kù)中檢索的多行記錄(使用SELECT語(yǔ)句)。利用游標(biāo),程序可以逐個(gè)地處理和遍歷一次檢索返回的整個(gè)記錄集。
?????為了處理SQL語(yǔ)句,Oracle將在內(nèi)存中分配一個(gè)區(qū)域,這就是上下文區(qū)。這個(gè)區(qū)包含了已經(jīng)處理完的行數(shù)、指向被分析語(yǔ)句的指針,整個(gè)區(qū)是查詢(xún)語(yǔ)句返回的數(shù)據(jù)行集。游標(biāo)就是指向上下文區(qū)句柄或指針。
?
二、游標(biāo)的分類(lèi):
1、靜態(tài)游標(biāo):靜態(tài)游標(biāo)是在編譯時(shí)知道其SELECT語(yǔ)句的游標(biāo)。靜態(tài)游標(biāo)又分為兩種類(lèi)型,隱式游標(biāo)和顯示游標(biāo)。
2、動(dòng)態(tài)游標(biāo):用戶為游標(biāo)使用的查詢(xún)直到運(yùn)行的時(shí)候才能確定,可以使用REF游標(biāo)和游標(biāo)變量滿足這個(gè)要求。為了使用引用游標(biāo),必須聲明游標(biāo)變量。有兩種類(lèi)型的REF游標(biāo):強(qiáng)類(lèi)型REF游標(biāo)和弱類(lèi)型REF游標(biāo)。
?
?
三、顯示游標(biāo)的用法:
顯示游標(biāo)被用于處理返回多行數(shù)據(jù)的SELECT?語(yǔ)句,游標(biāo)名通過(guò)CURSOR….IS?語(yǔ)句顯示地賦給SELECT?語(yǔ)句。
? ? ? ? (一)使用步驟;
?????? 1)聲明游標(biāo): CURSOR cursor_name IS select_statement
? ? ? ? 2)為查詢(xún)打開(kāi)游標(biāo): OPEN cursor_name
? ? ? ? 3)取得結(jié)果放入PL/SQL變量中;
? ? ? ? ? ? ? ? ? FETCH cursor_name INTO list_of_variables;
????????????? FETCH cursor_name INTO PL/SQL_record;
? ? ? ? 4)關(guān)閉游標(biāo)。 CLOSE cursor_name
注意:在聲明游標(biāo)時(shí), select_statement不能包含INTO子句。當(dāng)使用顯示游標(biāo)時(shí),INTO子句是FETCH語(yǔ)句的一部分。
例:顯示雇員的名稱(chēng)和薪水
-- 使用LOOP遍歷游標(biāo) DECLARE v_name emp.ename % TYPE; v_sal emp.sal % TYPE; CURSOR cus_emp IS SELECT ename,sal FROM emp; -- 聲明游標(biāo) BEGIN OPEN cus_emp; -- 打開(kāi)游標(biāo) LOOP FETCH cus_emp INTO v_name,v_sal; -- 提取游標(biāo) EXIT WHEN cus_emp % NOTFOUND; dbms_output.put_line( ' 第 ' || cus_emp % ROWCOUNT || ' 個(gè)用戶: name: ' || v_name || ' sal: ' || v_sal); END LOOP; CLOSE cus_emp; -- 關(guān)閉游標(biāo) END ;
顯示游標(biāo)的屬性:
%FOUND:只有在DML語(yǔ)句影響一行或者多行是,則返回TRUE;
%NOTFOUND:沒(méi)有影響任何行,則返回TRUE。
%ROWCOUNT:返回DML語(yǔ)句影響的行數(shù),沒(méi)有影響則返回0;
%ISOPEN:返回游標(biāo)是否打開(kāi),在執(zhí)行SQL之后,Oracle自動(dòng)關(guān)閉SQL游標(biāo),所以隱式游標(biāo)的%isopen屬性始終未false;
?
另一種方式:
-- 使用for來(lái)簡(jiǎn)化游標(biāo)遍歷 DECLARE CURSOR cus_emp IS SELECT ename,sal FROM emp; BEGIN FOR record_emp IN cus_emp LOOP dbms_output.put_line( ' 第 ' || cus_emp % ROWCOUNT || ' 個(gè)用戶: name: ' || record_emp.ename || ' sal: ' || record_emp.sal); END LOOP; END ;
record_emp是plsql聲明的的記錄變量,此變量的屬性為聲明為%ROWTYPE類(lèi)型,作用域在FOR循環(huán)之內(nèi),即在FOR循環(huán)外就不能訪問(wèn)了。
循環(huán)游標(biāo)的特性:
(1)從游標(biāo)中提取了所有記錄之后自動(dòng)終止。
(2)提取和處理游標(biāo)中的每一條記錄。
(3)如果在提取記錄之后%NOTFOUND屬性返回TRUE,則終止循環(huán)。如果未返回任何行,則不進(jìn)入循環(huán)。
?
游標(biāo)案例:
-- 給員工加薪,按員工入職時(shí)間進(jìn)行加薪,每年加100,1000封頂 DECLARE v_date emp.hiredate % TYPE; v_empno emp.empno % TYPE; v_money NUMBER ; CURSOR cur_emp IS SELECT empno,hiredate FROM emp; BEGIN OPEN cur_emp; LOOP FETCH cur_emp INTO v_empno,v_date; EXIT WHEN cur_emp % NOTFOUND; v_money : = 100 * ( 1990 - to_char(v_date, ' yyyy ' )); IF v_money < 1000 THEN UPDATE emp SET sal = sal + v_money WHERE empno = v_empno; ELSE UPDATE emp SET sal = sal + 1000 WHERE empno = v_empno; END IF ; END LOOP; END ;
?
四、隱式游標(biāo):
所有的隱式游標(biāo)都被假設(shè)為只返回一條記錄。
使用隱式游標(biāo)時(shí),用戶無(wú)需進(jìn)行聲明、打開(kāi)及關(guān)閉。PL/SQL隱含地打開(kāi)、處理,然后關(guān)掉游標(biāo)。多條sql語(yǔ)句 隱式游標(biāo)SQL永遠(yuǎn)指的是最后一條sql語(yǔ)句的結(jié)果,主要使用在update 和 delete語(yǔ)句上。
隱式游標(biāo)的四個(gè)屬性:
?
屬性 | 說(shuō)明 |
?SQL%rowcount | ?影響的記錄的行數(shù)整數(shù)(用來(lái)判斷插入,更新修改是否成功,必須在comit之前,否則提交后結(jié)果為0.) |
?SQL%found | ?影響到了記錄 true() |
?SQL%notfound | ?沒(méi)有影響到記錄 true |
?SQL%isopen | ?是否打開(kāi) 布爾值 永遠(yuǎn)是false |
例如:
DECLARE row_emp emp % ROWTYPE; BEGIN SELECT ename,sal INTO row_emp.ename,row_emp.sal FROM emp WHERE emp.empno = 7369 ; -- 判斷是否查到數(shù)據(jù) if (SQL % ROWCOUNT = 1 ) THEN dbms_output.put_line( ' 找到了 ' ); END IF ; -- 另一種方式判斷 IF (SQL % Found) THEN dbms_output.put_line( ' 找到了 ' ); END IF ; dbms_output.put_line( ' ename: ' || row_emp.ename || ' sal: ' || row_emp.sal); END ;
?
上述游標(biāo)自動(dòng)打開(kāi),并把相關(guān)值賦給對(duì)應(yīng)變量,然后關(guān)閉。執(zhí)行完后,PL/SQL變量rowemp.ename,rowemp.sal中已經(jīng)有了值。
五:動(dòng)態(tài)游標(biāo)
靜態(tài)游標(biāo)是在聲明就已經(jīng)確定查詢(xún)語(yǔ)句,如果用戶需要在運(yùn)行時(shí)動(dòng)態(tài)決定游標(biāo)執(zhí)行的查詢(xún),就需要使用動(dòng)態(tài)游標(biāo)(REF游標(biāo))。
動(dòng)態(tài)游標(biāo)分為兩類(lèi): 強(qiáng)類(lèi)型游標(biāo) 和 弱類(lèi)型游標(biāo) 。
動(dòng)態(tài)游標(biāo)使用步驟:
1、聲明動(dòng)態(tài)游標(biāo)類(lèi)型;
2、打開(kāi)游標(biāo),指定游標(biāo)查詢(xún);
3、提取游標(biāo)。
4、關(guān)閉游標(biāo)。
例:
強(qiáng)類(lèi)型游標(biāo), 使用return聲明的游標(biāo)為強(qiáng)類(lèi)型游標(biāo)。在對(duì)游標(biāo)進(jìn)行綁定查詢(xún)只能綁定游標(biāo)返回的類(lèi)型rowtype。
-- 強(qiáng)類(lèi)型的動(dòng)態(tài)游標(biāo),查詢(xún)emp表中的數(shù)據(jù) DECLARE TYPE ref_cur IS REF CURSOR -- 聲明游標(biāo)類(lèi)型 RETURN emp % ROWTYPE; -- 帶返回值的為強(qiáng)類(lèi)型動(dòng)態(tài)游標(biāo) refcur_emp ref_cur; -- 游標(biāo)類(lèi)型對(duì)象 v_emp emp % ROWTYPE; BEGIN OPEN refcur_emp FOR -- 將游標(biāo)綁定到一個(gè)查詢(xún)語(yǔ)句,因?yàn)槁暶鞯氖菑?qiáng)類(lèi)型,所以只能綁定emp; SELECT * FROM emp; LOOP FETCH refcur_emp INTO v_emp; -- 提取游標(biāo)內(nèi)容 EXIT WHEN refcur_emp % NOTFOUND; dbms_output.put_line(refcur_emp % Rowcount || ' 、name: ' || v_emp.ename || ' sal: ' || v_emp.sal); END LOOP; CLOSE refcur_emp; END ;
弱類(lèi)型游標(biāo):可以用來(lái)綁定多個(gè)查詢(xún)結(jié)果。
例:
-- 弱類(lèi)型游標(biāo) DECLARE TYPE refcur IS REF CURSOR ; -- 未定義返回類(lèi)型為弱類(lèi)型游標(biāo) rc refcur; v_name emp.ename % TYPE; v_deptname dept.dname % TYPE; BEGIN OPEN rc FOR SELECT ename,dname FROM emp e,dept d WHERE e.deptno = d.deptno; -- 綁定查詢(xún) LOOP FETCH rc INTO v_name,v_deptname; EXIT WHEN rc % NOTFOUND; dbms_output.put_line( ' name: ' || v_name || ' deptname: ' || v_deptname); END LOOP; CLOSE rc; END ;
?
例:
-- 根據(jù)輸入的內(nèi)容綁定游標(biāo) DECLARE TYPE refcur IS REF CURSOR ; rc refcur; v_tablename VARCHAR2 ( 10 ) : = ' &tab ' ; v_id NUMBER ; v_name VARCHAR2 ( 20 ); BEGIN IF (v_tablename = ' e ' ) THEN OPEN rc FOR SELECT e.empno,e.ename INTO v_id,v_name FROM emp e; dbms_output.put_line( ' =========員工信息============= ' ); Elsif(v_tablename = ' d ' ) THEN OPEN rc FOR SELECT d.deptno,d.dname INTO v_id,v_name FROM dept d; dbms_output.put_line( ' =========部門(mén)信息============= ' ); ELSE dbms_output.put_line( ' 輸入錯(cuò)誤,請(qǐng)輸入e或者d! ' ); RETURN ; END IF ; LOOP FETCH rc INTO v_id,v_name; dbms_output.put_line( ' # ' || rc % Rowcount || ' id: ' || v_id || ' name: ' || v_name); EXIT WHEN rc % NOTFOUND; END LOOP; END ;
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(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ì)您有幫助就好】元
