Oracle總結(二):Oracle遊標CURSOR

遊標 CURSOR

1遊標概述

  • 遊標(cursor)是數據庫系統在內存中開設的一個數據緩衝區,存放SQL語句的執行結果。
  • 每個遊標都有一個名字,用戶可以用SQL語句逐一從遊標中獲取記錄,並賦給變量做進一步處理。
  • 作用:用於定位結果集的行 和 遍歷結果集。
  • 遊標產生時間:當執行DML SQL語句時;
  • 遊標用於存放:結果集
  • 遊標有名字嗎:有,SQL或用戶給他取名
  • 遊標如何操作:用FETCH語句逐一從遊標中提取記錄,並賦給變量進一步處理
  • 同時可打開幾個遊標:多個,具體數量由數據庫初始化參數OPEN_CURSOR決定。

2遊標分類

  • 遊標分爲:靜態遊標(隱式和顯式)和REF遊標(+遊標變量)

2.1遊標的屬性

  • %FOUND SQL語句影響了一行或多行時爲true;
  • %NOTFOUND SQL語句沒有影響任何行時爲true(常用,沒找到爲T,就退出)
  • %ROWCOUNT SQL語句影響的行數;
  • %ISOPEN 遊標是否打開,始終爲false。

2.2靜態遊標

  • 靜態遊標是指結果集已經確實(靜態定義)的遊標。
  • 靜態遊標分:隱式遊標和顯示遊標。

2.2.1隱式遊標

在PL/SQL中隱式遊標在執行DML SQL(Insert/Delete/Update/Select)語句時自動創建、自動聲明、打開和關閉,其名SQL(注:所有的隱式遊標名都叫“SQL”);
示例:
使用遊標的屬性。

BEGIN
UPDATE emp SET sal=5000 WHERE empno=7369;
IF SQL%FOUND THEN
DBMS_OUTPUT.PUT_LINE( ‘表已更新’ );
END IF;
END;

提示:
在Java中,如對錶進行了增刪改操作,結果會返回n,表示在數據庫中多少行受影響。
我們通過 n>0 或 n=0 來判斷SQL代碼是否執行成功。
這個n 即SQL%ROWCOUNT屬性。

2.2.1顯示遊標

顯示遊標用於處理SELECT時返回多行的查詢;
增刪改時不會用顯示遊標;
顯示遊標需要手動的去做聲明、打開、提取、關閉操作。
示例:

顯示遊標操作

DECLARE
--聲明遊標:劃分存儲區域,注意此時並沒有執行Select語句。
CURSOR c_name IS
SELECT sal FROM emp WHERE empno=7369;
my_sal emp.sal%TYPE;
BEGIN
--打開遊標:執行select語句,獲得結果集存到遊標中,此時遊標指向結果集頭,而不是第一條記錄。
OPEN c_name;
--提取記錄:移動遊標取一條記錄
FETCH c_name INTO my_sal;
DBMS_OUTPUT.PUT_LINE(my_sal);
--關閉遊標:將遊標放入緩衝池中,沒有完全釋放資源,可重新打開。
CLOSE c_name;
END;

帶參數的顯示遊標

DECLARE
CURSOR c_name( dno NUMBER ) IS
SELECT * FROM emp WHERE deptno=dno;
my_a emp%ROWTYPE;
BEGIN
OPEN c_name(10); --打開遊標,並傳值
LOOP
FETCH c_name INTO my_a;
EXIT LOOP c_name%NOTFOUND;
DBMS_OUTPUT.PUT_LINE( '名字:'||my_a.ename );
END LOOP;
CLOSE c_name;
END;

For循環遊標

作用:簡化遊標處理代碼(簡化打開、提取、關閉)。
基本語法:
FOR r_index IN cursor_name LOOP
……
END LOOP;
示例:For循環遊標操作

DECLARE
CURSOR c_name IS
SELECT * FROM emp;
BEGIN
FOR i IN c_name LOOP
DBMS_OUTPUT.PUT_LINE( i.ename||' '||i.job );
END LOOP;
END;

註釋:如同foreach語句一樣,i默認爲行類型(%rowtype),自動打開、提取、關閉。

帶參數的For循環遊標

DECLARE
CURSOR c_name( dno number ) IS
SELECT * FROM emp WHERE deptno=dno;
BEGIN
FOR i IN c_name(30) LOOP
DBMS_OUTPUT.PUT_LINE( i.ename||' '||i.job );
END LOOP;
END;

遊標的嵌套問題

固名思義,就是在遊標中嵌套一個遊標。

示例:
列出所有部門的人員信息。
要求結果如下:
部門號:10 部門名稱:****
編號:** 姓名:**
編號:** 姓名:**
……
部門號:20 部門名稱:****
編號:** 姓名:**
編號:** 姓名:**
……
分析:
1.創建部門遊標,先將部門信息列出來;
2.在循環取部門信息時,再創建打開員工表遊標,進行讀取。

DECLARE
CURSOR mydc IS
SELECT * FROM dept;
mydr dept%ROWTYPE;--聲明dept部門表對象
CURSOR myec(dno NUMBER) IS
SELECT * FROM emp WHERE empno=dno;
myer emp%ROWTYPE;--聲明emp員工表對象
BEGIN
--先打開部門結果集遊標
OPEN mydc;
LOOP
FETCH mydc INTO mydr;
EXIT LOOP mydc%NOTFOUND;--提取完退出LOOP
DBMS_OUTPUT.PUT_LINE( '部門號:'||mydr.deptno||' 部門名稱:'||mydr.dname );
--再打開員工結果集遊標,入部門編號
OPEN myec(mydr.deptno);
LOOP
FETCH myec INTO myer;
EXIT LOOP myec%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(' 編號:'||myer.empno||' 姓名:'||myer.ename);
END LOOP;
CLOSE myec;
END LOOP;
CLOSE mydc;
END;
--使用For循環簡化
DECLARE
CURSOR mydc IS
SELECT * FROM dept;
CURSOR myec(dno number) IS
SELECT * FROM emp WHERE empno=dno;
BEGIN
--遍歷部門結果集遊標
FOR i INT mydc LOOP
DBMS_OUTPUT.PUT_LINE( '部門號'||i.deptno||' 部門名稱:'||i.dname );
--遍歷員工結果集遊標,傳下部門編號
FOR j INT myec(i.detpno) LOOP
DBMS_OUTPUT.PUT_LINE( ' 編號'||j.empno||' 姓名:'||j.ename );
END LOOP;
END LOOP;
END;

3REF遊標

REF遊標也叫動態遊標,動態SQL執行時產生。
REF遊標更應該被稱之爲遊標類型,而遊標變量則爲該類型的遊標。

3.1創建REF遊標+遊標變量

基本語法:
–創建REF遊標
TYPE ref_cursor_name IS REF CURSOR
[RETURN 返回類型];
–聲明REF遊標變量
遊標變量 ref_cursor_name;
示例:
創建個REF遊標類型
TYPE ref_name IS REF CURSOR; --定義弱遊標類型,名字叫ref_name
c_name ref_name;

3.2 REF遊標分類

強類型:帶RETURN返回類型
弱類型:不帶RETURN返回類型
相對來說,弱類型更爲靈活。
示例:
聲明強類型REF遊標+遊標變量
DECLARE
TYPE c_type IS REF CURSOR
RETURN emp%ROWTYPE;
c_name c_type;

3.3 打開遊標變量

OPEN cursor_name FOR 查詢結果集;
示例:用REF遊標+遊標變量顯示數據

DECLARE
TYPE my_t IS REF CURSOR
RETURN emp%ROWTYPE; --聲明一個遊標類型
myc my_t; --定義一個REF類型的遊標變量
myr emp%ROWTYPE;
BEGIN
OPEN myc FOR
SELECT * FROM emp;
LOOP
FETCH myc INTO myr;
EXIT WHEN myc%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(myr.ename);
END LOOP;
CLOSE myc;
END;

4標變量的優點和限制

  • 遊標變量功能強大,可以簡化數據處理;
  • 遊標變量優點:
    a.可從不同的select語句中提取結果集;
    b.可以作爲過程的參數進行傳遞;
    c.可以引用遊標的所有屬性;
    d.可以進行賦值運算;
  • 遊標變量的限制:
    a.不能在程序包中聲明遊標變量;
    b.for update子句不能與遊標變量一起使用;
    c.不能使用比較運算符。
    三、動態語句拼接
    設定一個遊標變量來執行動態的sql語句。
    數據庫管理員、設計師常用的知識點。
    基本語法:
    OPEN 遊標名 FOR ‘SELECT … >:1 …’;
    USEING 變量名;
    示例1:
    OPEN cursor_name FOR
    ‘SELECT * FROM emp WHERE sal>:1 ORDER BY sal DESC’
    USEING p_sal;
    解釋:
    –設置佔位符:sal>:1動態拼接(相當於JDBC中的?佔位符)
    –填充佔位符:將變量p_sal的值代入SELECT中“:1”位置處
    –如有多個動態拼接處,請設置:2,:3,……,同時using 後面變量用逗號分隔。
    示例2:
DECLARE
r_emp emp%ROWTYPE;
--定義REF遊標及遊標變量
TYPE c_type IS REF CURSOR;
cur c_type;
p_salary NUMBER;
BEGIN
p_salary := 2500;
--打開遊標
OPEN cur FOR
'select * from emp where sal>:1 order by sal desc'
--填充佔位符
USING p_salary;
DBMS_OUTPUT.PUT_LINE('薪水大於'|| p_salary ||'的員工有:');
LOOP
--提取遊標中的數據到變量r_emp
FETCH cur INTO r_emp;
EXIT WHEN cur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('編號:'|| r_emp.empno||'姓名:'||r_emp.ename||'薪水:'||r_emp.sal);
END LOOP;
--關閉遊標
CLOSE cur;
END;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章