一、顯示游標(biāo)
PL/SQL 游標(biāo)包含隱含游標(biāo)和顯示游標(biāo)等兩種游標(biāo)類(lèi)型,其中隱含游標(biāo)用于處理SELECT INTO和 DML語(yǔ)句,而顯示游標(biāo)則專(zhuān)門(mén)用于處理SELECT 語(yǔ)句返回的多行數(shù)據(jù)。
1、使用顯示游標(biāo)
為了處理SELECT 語(yǔ)句返回的多行數(shù)據(jù),開(kāi)發(fā)人員可以使用顯示游標(biāo),使用顯示游標(biāo)包括定義游標(biāo)、打開(kāi)游標(biāo)、提取數(shù)據(jù)和關(guān)閉游標(biāo)四個(gè)階段.
1.1定義游標(biāo)
使用顯示游標(biāo)之前,必須首先在定義部分定義游標(biāo)。定義游標(biāo)用于指定游標(biāo)多對(duì)應(yīng)的SELECT語(yǔ)句,語(yǔ)法如下:
CURSOR cursor_name IS select_statement
如上所示,cursor_name用于定義游標(biāo)名稱(chēng);select_statement用于指定游所對(duì)應(yīng)的SELECT 語(yǔ)句。
1.2打開(kāi)游標(biāo)
當(dāng)打開(kāi)游標(biāo)時(shí),Oracle會(huì)執(zhí)行游標(biāo)所對(duì)應(yīng)的SELECT語(yǔ)句,并且SELECT語(yǔ)句的結(jié)果暫時(shí)存放到結(jié)果集中,語(yǔ)法如下:
OPEN cursor_name;
該游標(biāo)名必須是在定義部分已經(jīng)定義的游標(biāo)。
1.3提取數(shù)據(jù)
在打開(kāi)游標(biāo)之后,SELECT 語(yǔ)句的結(jié)果被臨時(shí)存放到游標(biāo)結(jié)果集中.為了處理結(jié)果集中的數(shù)據(jù),需要使用FETCH語(yǔ)句 提取游標(biāo)數(shù)據(jù).在Oracle 9i之前,使用FETCH語(yǔ)句,每次只能提取一行數(shù)據(jù);從Oracle 9i之后,通過(guò)使用FETCH.....BULK COLLECT INTO語(yǔ)句,每次可以提取多行數(shù)據(jù)。語(yǔ)法如下:
語(yǔ)法一:FETCH cursor_name INTO variable1,variable2 ,....;
語(yǔ)法二:FETCH cursor_name BULK COLLECT INTO collect1,collect2,...[LIMIT rows];
如上所示,variable用于指定接收游標(biāo)數(shù)據(jù)的變量;collect用于指定接收游標(biāo)結(jié)果的集合變量。注意,當(dāng)使用語(yǔ)法一時(shí),必須使用循環(huán)語(yǔ)句處理結(jié)果集的所有數(shù)據(jù)。
1.4、關(guān)閉游標(biāo)
在提取并處理了結(jié)果集的所有數(shù)據(jù)之后,就可以關(guān)閉游標(biāo)并釋放其結(jié)果集了。 語(yǔ)法如下:
CLOSE cursor_name;
2、顯示游標(biāo)屬性
顯示游標(biāo)屬性用于返回顯示游標(biāo)的執(zhí)行信息,這些屬性包括%ISOPEN,%FOUND,%NOTFOUND和%ROWCOUNT。當(dāng)使用顯示游標(biāo)屬性時(shí),必須要在顯示游標(biāo)屬性之前帶有顯示游標(biāo)名作為前綴(游標(biāo)名.屬性名).
2.1、%ISOPEN
該屬性用于確定游標(biāo)是否已經(jīng)打開(kāi)。如果游標(biāo)已經(jīng)打開(kāi),則返回值位True;如果游標(biāo)沒(méi)有打開(kāi),則返回值為False。示例如下:
- IF c1%ISFOUND THEN ----如果游標(biāo)打開(kāi),則執(zhí)行相應(yīng)操作
- .....
- ELSE ----如果游標(biāo)未打開(kāi),則打開(kāi)游標(biāo)
- OPEN c1;
- END IF;
2.2、%FOUND
該屬性用于檢查是否從結(jié)果集中提取到了數(shù)據(jù)。如果提取到數(shù)據(jù),則返回值位TRUE;如果沒(méi)有提取到數(shù)據(jù),返回值位FALSE。示例如下:
- LOOP
- FETCH c1 INTO var1,var2 ----提取數(shù)據(jù)到變量中
- IF c1%FOUND THEN ----如果提取到數(shù)據(jù)則進(jìn)行處理
- ....
- ELSE ----如果未提取到數(shù)據(jù),則退出循環(huán)
- EXIT;
- END IF;
- END LOOP;
2.3、%NOTFOUND
該屬性與%FOUND屬性恰好相反。如果提取到數(shù)據(jù),則返回值位FALSE;如果沒(méi)有提取到數(shù)據(jù),則返回值為T(mén)RUE。示例如下:
- LOOP
- FETCH c1 INTO var1,var2; -----提取數(shù)據(jù)到變量中
- EXIT WHEN c1%NOTFOUND;
- ...
- END LOOP;
2.4、ROWCOUNT
該屬性用于返回到當(dāng)前行為為止已經(jīng)提取到的實(shí)際行數(shù)。示例如下:
- LOOP
- FETCH c1 INTO my_ename,my_deptno;
- IF c1%ROWCOUNT >10 THEN
- ....
- END IF;
- ...
- END LOOP;
3、顯示游標(biāo)使用示例
示例一:在顯示游標(biāo)中使用FETCH INTO 語(yǔ)句
在Oracle9i 之前,使用FETCH.....INTO語(yǔ)句每次只能處理一行數(shù)據(jù)。為了處理結(jié)果集中的多行數(shù)據(jù),必須要使用循環(huán)語(yǔ)句進(jìn)行處理。下面以在PL/SQL塊中顯示部門(mén)10的所有雇員名及其工資為例,說(shuō)明在顯示游標(biāo)中使用FETCH...INTO語(yǔ)句的方法。示例如下:
- DECLARE
- CURSOR emp_cursor IS
- SELECT ename,sal FROM emp WHERE deptno=10; ----多行數(shù)據(jù)
- v_ename emp.ename%TYPE;
- v_sal emp.sal%TYPE;
- BEGIN
- OPEN emp_cursor;
- LOOP
- FETCH emp_cursor INTO v_ename,v_sal ; ---每次只能提取一行數(shù)據(jù),所以放在循環(huán)語(yǔ)句里面
- EXIT WHEN emp_cursor%NOTFOUND;
- dbms_output.put_line(v_ename||': '||v_sal);
- END LOOP;
- CLOSE emp_cursor;
- END;
示例二、在顯示游標(biāo)中,使用FETCH....BULK COLLECT INTO 語(yǔ)句取得所有數(shù)據(jù)。
從Oracle9i 開(kāi)始,通過(guò)使用FETCH...BULK COLLECT INTO 語(yǔ)句,一次就可以取得結(jié)果集中的所有數(shù)據(jù)。下面以顯示部門(mén)10的所有雇員名為例,說(shuō)明使用FETCH..BULK COLLECT INTO 取得所有數(shù)據(jù)的方法。示例如下:
- DECLARE
- CURSOR emp_cursor IS
- SELECT ename FROM emp WHERE deptno=10;
- TYPE ename_table_type IS TABLE OF VARCHAR2(10);
- ename_table ename_table_type;
- BEGIN
- OPEN emp_cursor;
- FETCH emp_cursor BULK COLLECT INTO ename_table;
- FOR i IN 1.. ename_table.COUNT LOOP
- dbms_output.put_line(ename_table(i));
- END LOOP;
- CLOSE emp_cursor;
- END;
示例三、使用游標(biāo)屬性
當(dāng)使用顯示游標(biāo)時(shí),為了取得顯示游標(biāo)的執(zhí)行信息,需要使用顯示游標(biāo)屬性。下面以使用顯示游標(biāo)屬性%ISOPEN和%ROWCOUNT為例,說(shuō)明在PL/SQL塊中使用顯示游標(biāo)屬性的方法。示例如下:
- DECLARE
- CURSOR emp_cursor IS
- SELECT ename FROM emp WHERE deptno=10;
- TYPE ename_table_type IS TABLE OF VARCHAR2(10);
- ename_table ename_table_type;
- BEGIN
- IF NOT emp_cursor%ISOPEN THEN ------如果游標(biāo)未打開(kāi),則打開(kāi)游標(biāo)
- OPEN emp_cursor;
- END IF;
- FETCH emp_cursor BULK COLLECT INTO ename_table;
- dbms_output.put_line('提取的總計(jì)行數(shù):'||emp_cursor%ROWCOUNT); ------顯示總計(jì)行數(shù)
- CLOSE emp_cursor;
- END;
示例四、基于游標(biāo)定義記錄變量
使用%ROWTYPE屬性不僅可以基于表和視圖定義記錄變量,也可以基于游標(biāo)定義記錄變量。當(dāng)基于游標(biāo)定義記錄變量時(shí),記錄成員名實(shí)際就是SELECT語(yǔ)句的列名或列別名。為了簡(jiǎn)化顯示游標(biāo)的數(shù)據(jù)處理,建議開(kāi)發(fā)人員使用記錄變量存放游標(biāo)數(shù)據(jù)。下面以顯示所有雇員名及其工資為例,說(shuō)明在處理顯示游標(biāo)數(shù)據(jù)時(shí)使用記錄變量的方法。示例如下:
- DECLARE
- CURSOR emp_cursor IS
- SELECT ename,sal FROM emp;
- emp_record emp_cursor%ROWTYPE; ----基于游標(biāo)定義記錄變量
- BEGIN
- OPEN emp_cursor;
- LOOP
- FETCH emp_cursor INTO emp_record; ------使用記錄變量存放游標(biāo)數(shù)據(jù)
- EXIT WHEN emp_cursor%NOTFOUND;
- dbms_output.put_line('雇員名:'||emp_record.ename||',雇員工資:'||emp_record.sal);
- END LOOP;
- CLOSE emp_cursor;
- END;
-
二、游標(biāo)FOR循環(huán)
游標(biāo)FOR循環(huán)是在PL/SQL塊中使用游標(biāo)最簡(jiǎn)單的方式,簡(jiǎn)化了對(duì)游標(biāo)的處理。當(dāng)使用游標(biāo)FOR循環(huán)時(shí),Oracle會(huì)隱含的打開(kāi)游標(biāo)、提取游標(biāo)數(shù)據(jù)并關(guān)閉游標(biāo)。使用游標(biāo)FOR循環(huán)的語(yǔ)法如下:
- FOR record_name IN cursor_name LOOP
- statement1;
- statement2;
- ...
- END LOOP;
如上所示,cursor_name是已經(jīng)定義的游標(biāo)名;record_name是Oracle隱含定義的記錄變量名。當(dāng)使用游標(biāo)FOR循環(huán)時(shí),在執(zhí)行循環(huán)體內(nèi)容之前,Oracle會(huì)隱含的打開(kāi)游標(biāo),并且沒(méi)循環(huán)一次提取一次數(shù)據(jù),在提取了所有數(shù)據(jù)之后,會(huì)自動(dòng)退出循環(huán)并隱含的關(guān)閉游標(biāo)。
1.使用游標(biāo)FOR循環(huán)
當(dāng)使用游標(biāo)開(kāi)發(fā)PL/SQL程序時(shí),為了簡(jiǎn)化程序代碼,建議大家使用游標(biāo)FOR循環(huán)。下面以順序顯示EMP表的所有雇員為例,說(shuō)明使用游標(biāo)FOR循環(huán)的方法。示例如下:
- DECLARE
- CURSOR emp_cursor IS SELECT ename,sal FROM emp;
- BEGIN
- FOR emp_record IN emp_cursor LOOP
- dbms_output.put_line('第'||emp_cursor%ROWCOUNT||'個(gè)雇員:'||emp_record.ename);
- END LOOP;
- END;
2.在游標(biāo)FOR循環(huán)中直接使用子查詢(xún)
當(dāng)使用游標(biāo)FOR循環(huán)時(shí),習(xí)慣做法是首先在定義部分定義游標(biāo),然后在游標(biāo)FOR循環(huán)中使用該游標(biāo)。如果在使用游標(biāo)FOR循環(huán)時(shí),不需要使用任何的游標(biāo)屬性,那么可以在游標(biāo)FOR循環(huán)中使用子查詢(xún).下面以顯示EMP的所有雇員名為例,說(shuō)明在游標(biāo)FOR循環(huán)中直接使用子查詢(xún)的方法。示例如下:
- BEGIN
- FOR emp_record IN
- (SELECT ename,sal FROM emp) LOOP
- dbms_output.put_line(emp_record.ename);
- END LOOP;
- END;
三、使用游標(biāo)變量
類(lèi)似C語(yǔ)言中的指針變量,PL/SQL的游標(biāo)變量中存放著只想內(nèi)存地址的指針。當(dāng)顯示使用游標(biāo)時(shí),需要在定義部分指定其所對(duì)應(yīng)的SELECT語(yǔ)句;而使用游標(biāo)變量時(shí),開(kāi)發(fā)人員可以在打開(kāi)游標(biāo)變量時(shí)指定其所對(duì)應(yīng)的SELECT語(yǔ)句。
1、游標(biāo)變量使用步驟
在PL/SQL塊中使用游標(biāo)變量包括定義游標(biāo)變量、打開(kāi)游標(biāo)變量、提取游標(biāo)數(shù)據(jù)、關(guān)閉游標(biāo)等四個(gè)階段。具體步驟如下:
(1)定義REF CURSOR類(lèi)型和游標(biāo)變量
為了在PL/SQL塊中定義游標(biāo)變量,必須首先定義REF CURSOR 類(lèi)型,然后才能定義游標(biāo)變量。定義REF CURSOR類(lèi)型和游標(biāo)變量的語(yǔ)法如下:
- TYPE ref_type_name IS REF CURSOR [RETURN return_type];
- cursor_variable ref_type_name;
如上所示,ref_type_name用于指定自定義的類(lèi)別名;RETURN 子句用于指定REF CURSOR返回結(jié)果的數(shù)據(jù)類(lèi)型;cursor_variable用于指定游標(biāo)變量名。注意:當(dāng)指定RETURN子句時(shí),其數(shù)據(jù)類(lèi)型必須是記錄類(lèi)型;另外,不能在包內(nèi),定義游標(biāo)變量.
(2) 打開(kāi)游標(biāo)
在定義游標(biāo)變量之后,為了引用該游標(biāo)變量,在打開(kāi)游標(biāo)時(shí),需要指定其所對(duì)應(yīng)的SELECT語(yǔ)句。當(dāng)打開(kāi)游標(biāo)時(shí),會(huì)執(zhí)行游標(biāo)變量所對(duì)應(yīng)的SELECT語(yǔ)句,并將SELECT語(yǔ)句結(jié)果存放到游標(biāo)結(jié)果集中。語(yǔ)法如下:
- OPEN cursor_variable FOR select_statement;
如上所示,select_statement用于指定游標(biāo)所對(duì)應(yīng)的SELECT語(yǔ)句。
(3)提取游標(biāo)數(shù)據(jù)
和顯示游標(biāo)的描述差不多.
(4)關(guān)閉游標(biāo)變量
在提取并處理了所有游標(biāo)數(shù)據(jù)之后,就可以關(guān)閉游標(biāo)變量并釋放其結(jié)果集了。語(yǔ)法如下:
CLOSE cursor_variable;
2、游標(biāo)使用示例
示例一:在定義REF CURSOR類(lèi)型時(shí)不指定RETURN 子句
如果在定義REF CURSOR類(lèi)型時(shí),不指定RETUEN 子句,那么在打開(kāi)游標(biāo)時(shí)可以指定熱任何的SELECT語(yǔ)句。下面以順序的顯示所有雇員名稱(chēng)為例,說(shuō)明使用游標(biāo)變量(不使用RETURN子句)的方法。示例如下:
- DECLARE
- TYPE emp_cursor_type IS REF CURSOR;
- emp_cursor emp_cursor_type;
- emp_record emp%ROWTYPE;
- BEGIN
- OPEN emp_cursor FOR SELECT * FROM emp WHERE deptno=10;
- LOOP
- FETCH emp_cursor INTO emp_record;
- EXIT WHEN emp_cursor%NOTFOUND;
- dbms_output.put_line('第'||emp_cursor%ROWCOUNT||'個(gè)雇員:'||emp_record.ename);
- END LOOP;
- CLOSE emp_cursor;
- END;
示例二:在定義REF CURSOR類(lèi)型時(shí)指定RETUEN 子句
如果在定義REF CURSOR 類(lèi)型時(shí)指定了RETURN 子句,在打開(kāi)游標(biāo)時(shí)SELECT 語(yǔ)句的返回結(jié)果必須與RETURN 子句指定的記錄類(lèi)型相匹配。下面以順序顯示部門(mén)20單位所有雇員名為例, 說(shuō)明使用游標(biāo)變量(使用RETURN子句)的方法。示例如下:
- DECLARE
- TYPE emp_record_type IS RECORD(
- name VARCHAR2(10),salary NUMBER(6,2));
- TYPE emp_cursor_type IS REF CURSOR
- RETURN emp_record_type;
- emp_cursor emp_cursor_type;
- emp_record emp_record_type;
- BEGIN
- OPEN emp_cursor FOR SELECT ename,sal FROM emp
- WHERE deptno=20;
- LOOP
- FETCH emp_cursor INTO emp_record;
- EXIT WHEN emp_cursor%NOTFOUND;
- dbms_output.put_line('第'||emp_cursor%ROWCOUNT||'個(gè)雇員:'||emp_record.name);
- END LOOP;
- CLOSE emp_cursor;
- END;
如上所示,因?yàn)槎xREF CURSOR 類(lèi)型時(shí)指定了RETURN 子句,所以游標(biāo)子查詢(xún)的返回結(jié)果必須與記錄類(lèi)型emp_record_type相匹配。例如,如果在打開(kāi)游標(biāo)變量時(shí)指定"SELECT ename,sal,deptno FROM emp WHERE deptno=20;",那么在執(zhí)行PL/SQL時(shí)會(huì)報(bào)錯(cuò)的.
后續(xù)內(nèi)容更精彩,敬請(qǐng)關(guān)注!
|