1. 遊標: 容器,存儲SQL語句影響行數。
2. 遊標類型: 隱式遊標,顯示遊標,REF遊標。其中,隱式遊標和顯示遊標屬於靜態遊標(運行前將遊標與SQL語句關聯),REF遊標屬於動態遊標(運行時將遊標與SQL語句關聯)。
3. 隱式遊標: DML語句對應的遊標,由Oracle自動管理,也稱SQL遊標。(所有的DML操作都被Oracle內部解析爲一個cursor名爲SQL的隱式遊標)
q 隱式遊標的屬性有:
q %FOUND – SQL 語句影響了一行或多行時爲 TRUE
q %NOTFOUND – SQL 語句沒有影響任何行時爲TRUE
q %ROWCOUNT – SQL 語句影響的行數
q %ISOPEN - 遊標是否打開,始終爲FALSE
舉例說明:
Sql代碼
1. declare
2.
3. v_empno emp.empno %type:=7000;
4.
5. begin
6.
7. update emp set ename='fxe' where empno=v_empno;
8.
9. if SQl%found then
10.
11. dbms_output.put_line(SQL%rowcount||'Delete Ok!');
12.
13. end if;
14.
15. if SQL%notfound then -- 一條SQL就表示是一個隱式遊標
16.
17. dbms_output.put_line('僱員編號'||v_empno||'不存在');
18.
19. end if;
20.
21. end;
4. 顯示遊標操作:
(1)聲明遊標(關聯SQL語句) cursor+遊標名 is/as sql語句
(2)打開遊標(執行SQL語句,填充遊標) open+遊標名
(3)提取遊標的行 fetch 遊標名 into 行類型變量
(4)關閉遊標 close+遊標名
舉例說明:
Sql代碼
1. declare
2.
3. cursor emp_cur is select * from emp; --聲明無參顯示遊標 關聯SQL
4.
5. empRecord emp%rowtype; --表示類型爲一條記錄
6.
7. begin
8.
9. open emp_cur; --打開遊標
10.
11. loop
12.
13. fetch emp_cur into empRecord; --取出emp_cur 這個遊標所對應的記錄放入empRecord變量裏
14.
15. exit when emp_cur%notfound; --當沒記錄時,退出循環
16.
17. dbms_output.put_line(empRecord.ename); --打印ename
18.
19. end loop;
20.
21. close emp_cur;
22.
23. end;
5. 帶參數的顯示遊標
例:
Sql代碼
1. declare
2.
3. destination varchar2(20);
4.
5. cursor emp_cur(dest varchar2) --聲明帶參顯示遊標
6.
7. is select * from emp where empno=dest; --關聯到SQL
8.
9. empRecord emp%rowtype; -- 行類弄的變量empRecord
10.
11. begin
12.
13. destination:=&empno; --彈出用戶輸入框
14.
15. open emp_cur(destination); --打開遊標
16.
17. loop
18.
19. fetch emp_cur into empRecord; -- 循環每一遊標所對應的記錄放入empRecord
20.
21. exit when emp_cur%notfound;
22.
23. dbms_output.put_line(empRecord.ename);
24.
25. end loop;
26.
27. close emp_cur;
28.
29. end;
----輸入參數:7369
6. 使用顯式遊標更新行
q 允許使用遊標刪除或更新活動集中的行
q 聲明遊標時必須使用 SELECT … FOR UPDATE語句
例:
Sql代碼
1. declare
2.
3. old_sal number(4);
4.
5. emp_name varchar2(20);
6.
7. cursor emp_cur is select ename,sal from emp --聲明顯示遊標,關聯SQL
8.
9. where sal<1000
10.
11. for update of sal; -- 定義的遊標會讓數據庫對涉及的行(對應的列)加鎖,別的會話如果要訪問該遊標中的行便會進入等待狀態。
12. --如果別的會話一直不解鎖,那麼你的select就會一直等待下去,如果你不想等,只需在for update後面加上nowait就可以解決這個問題了,這樣你的選擇會立即返回。
13. begin
14.
15. open emp_cur;
16.
17. loop
18.
19. fetch emp_cur into emp_name,old_sal;
20.
21. exit when emp_cur%notfound;
22.
23. update emp set sal=1.1*old_sal --更新數據
24.
25. where current of emp_cur; --作用範圍就只在你循環的當前行的範圍中了
26.
27. dbms_output.put_line('更新成功!');
28.
29. end loop;
30.
31. end;
7.循環遊標
q 循環遊標用於簡化遊標處理代碼
q 當用戶需要從遊標中提取所有記錄時使用
q 循環遊標的語法如下:
Sql代碼
1. FOR <record_index> IN <cursor_name>
2.
3. LOOP
4.
5. <executable statements>
6.
7. END LOOP;
FOR <record_index> IN <cursor_name>
LOOP
<executable statements>
END LOOP;
例:
Java代碼
1. declare
2.
3. cursor emp_cur is select empno,ename,sal from emp; --顯示遊標
4.
5. begin
6.
7.
8. for empRecord in emp_cur --empRecord 表示每行,emp_cur 所有行
9.
10. loop
11.
12. dbms_output.put_line(empRecord.empno
13.
14. ||empRecord.ename||empRecord.sal);
15.
16. end loop;
17.
18. end;
8.REF遊標和遊標變量
q REF 遊標和遊標變量用於處理運行時動態執行的 SQL 查詢
q 創建遊標變量需要兩個步驟:
q 聲明 REF 遊標類型
q 聲明 REF 遊標類型的變量
q 用於聲明 REF 遊標類型的語法爲:
TYPE <ref_cursor_name> IS REF CURSOR
[RETURN <return_type>];
q 打開遊標變量的語法如下:
OPEN cursor_name FOR select_statement;
聲明強類型的REF遊標
type emp_cur is ref cursor return emp%rowtype;
empRecord emp_cur;
聲明弱類型的REF遊標
type emp_cur is ref cursor;
empRecord emp_cur;
例:
Sql代碼
1. DECLARE
2.
3. TYPE emp_cur IS REF CURSOR
4.
5. RETURN emp%ROWTYPE; -- 聲明強類型的REF遊標(只能返回emp結構類弄的遊標)
6.
7. empObj emp_cur; --聲明 REF 遊標類型的變量
8.
9. empRecord emp%ROWTYPE; --行數據類開的變量
10.
11. BEGIN
12.
13. OPEN empObj FOR --打開ref類型的遊標
14.
15. SELECT * FROM emp;
16.
17. loop
18.
19. FETCH empObj INTO empRecord; --一行一行取出
20.
21. exit when empObj%notfound;
22.
23. dbms_output.put_line(empRecord.ename);
24.
25. end loop;
26.
27. CLOSE empObj;
28.
29. END;
9.遊標變量的優點和限制
q 遊標變量的功能強大,可以簡化數據處理。
q 遊標變量的優點有:
q 可從不同的 SELECT 語句中提取結果集
q 可以作爲過程的參數進行傳遞
q 可以進行賦值運算
q 使用遊標變量的限制:
q 不能在程序包中聲明遊標變量(這兒指的不是聲明遊標)
q FOR UPDATE子句不能與遊標變量一起使用
q 不能使用比較運算符
今天遇到的問題:
當使用帶參數的顯示遊標時,比如說使用的參數爲輸入參數,不能在SQL語句中直接寫輸入參數名字,否則解析不到,視爲無效。
正確的寫法:DECLARE
CURSOR cSafeID(report_year2 NUMBER) IS
SELECT t.accident_remark
FROM nssrf_v_s_monthly_report t
WHERE t.report_year =report_year2;
BEGIN
OPEN cSafeID(report_year);
------------------其中report_year爲輸入參數
錯誤的寫法:
DECLARE
CURSOR cSafeID IS
SELECT t.accident_remark
FROM nssrf_v_s_monthly_report t
WHERE t.report_year =report_year;
BEGIN
OPEN cSafeID;
-----------------語句中解析不到report_year的值
ORACLE遊標管理
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.