※隱式游標
就是不用打出「CURSOR」關鍵字,有四種,參考官網※%ROWCOUNT
DECLARE xxx_count NUMBER; BEGIN SELECT COUNT(*) INTO xxx_count FROM EMP; DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT); INSERT INTO DEPT VALUES(50, '業務部', '舊金山'); DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT); UPDATE DEPT SET DNAME='採購部' WHERE DEPTNO = 50; DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT); DELETE FROM DEPT WHERE DEPTNO = 50; DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT); END;
※使用%ROWCOUNT可得知操作的行數,此例的結果是4個1
※%FOUND、%NOTFOUND
DECLARE BEGIN UPDATE EMP SET SAL = SAL * 1.2; IF SQL%FOUND THEN DBMS_OUTPUT.PUT_LINE('修改了' || SQL%ROWCOUNT || '筆'); ELSE DBMS_OUTPUT.PUT_LINE('沒有資料被修改'); END IF; END;
※顯式游標的查詢
就是要明確的打出「CURSOR」關鍵字※和LOOP、WHILE迴圈配合使用
DECLARE CURSOR xxx_cur IS SELECT * FROM DEPT; xxx_dept DEPT%ROWTYPE; BEGIN IF NOT xxx_cur%ISOPEN THEN OPEN xxx_cur; END IF; /* FETCH xxx_cur INTO xxx_dept; WHILE xxx_cur%FOUND LOOP DBMS_OUTPUT.PUT(xxx_cur%ROWCOUNT); DBMS_OUTPUT.PUT_LINE('=' || xxx_dept.dname); FETCH xxx_cur INTO xxx_dept; END LOOP; */ LOOP FETCH xxx_cur INTO xxx_dept; EXIT WHEN xxx_cur%NOTFOUND; DBMS_OUTPUT.PUT(xxx_cur%ROWCOUNT); DBMS_OUTPUT.PUT_LINE('=' || xxx_dept.dname); END LOOP; CLOSE xxx_cur; END;
※以上是兩種迴圈和游標的使用
※CURSOR xxx_cur IS SELECT * FROM DEPT 是省略寫法,全部是
CURSOR xxx_cur RETURN DEPT%ROWTYPE IS SELECT * FROM DEPT,也就是多了RETURN DEPT%ROWTYPE,因為查的是DEPT,所以預設也回傳DEPT的ROWTYPE,所以可以省略
※和FOR迴圈配合使用
DECLARE CURSOR xxx_cur IS SELECT * FROM DEPT; xxx_dept DEPT%ROWTYPE; BEGIN DBMS_OUTPUT.PUT_LINE('方法一'); FOR xxx_dept IN xxx_cur LOOP DBMS_OUTPUT.PUT(xxx_cur%ROWCOUNT); DBMS_OUTPUT.PUT_LINE('=' || xxx_dept.dname); END LOOP; DBMS_OUTPUT.PUT_LINE(CHR(10) || '方法二'); FOR xxx_dept IN (SELECT * FROM DEPT) LOOP DBMS_OUTPUT.PUT_LINE(xxx_dept.dname); END LOOP; END;
※結果:
方法一
1=ACCOUNTING
2=RESEARCH
3=SALES
4=OPERATIONS
方法二
ACCOUNTING
RESEARCH
SALES
OPERATIONS
※和FOR迴圈配合時,不需要打開和關閉游標,也不用判斷哪時跳離迴圈,一切都交給系統控制,所以大部分的人都使用這一種
※方法一和方法二的差別就在方法二直接將SQL寫進去了,所以也無法使用%ROWCOUNT
※有參數的游標
DECLARE CURSOR xxx_cur(ooo DEPT.DEPTNO%TYPE) IS SELECT * FROM DEPT WHERE DEPTNO = ooo; BEGIN FOR xxx_dept IN xxx_cur(&pk) LOOP DBMS_OUTPUT.PUT(xxx_cur%ROWCOUNT || ' '); DBMS_OUTPUT.PUT(xxx_dept.deptno || ' '); DBMS_OUTPUT.PUT(xxx_dept.dname || ' '); DBMS_OUTPUT.PUT_LINE(xxx_dept.loc); END LOOP; END;
※結果:
1 10 ACCOUNTING NEW YORK
※&pk為使用者輸入的參數值
※LOOP和WHILE要寫在OPEN xxx_cur(&pk)
※注意傳進去的參數不能用來判斷,如果是in的話,網路有用一種子查詢的方式,但我沒試出來,我用的是第26篇的動態SQL解決in的問題
※和陣列配合使用
DECLARE CURSOR xxx_cur IS SELECT * FROM DEPT; TYPE xxx_index IS TABLE OF DEPT%ROWTYPE INDEX BY PLS_INTEGER; xxx xxx_index; BEGIN FOR xxx_dept IN xxx_cur LOOP xxx(xxx_dept.deptno) := xxx_dept; DBMS_OUTPUT.PUT_LINE(xxx(xxx_dept.deptno).dname); END LOOP; END;
※結果:
ACCOUNTING
RESEARCH
SALES
OPERATIONS
※和巢狀表配合使用
DECLARE CURSOR xxx_cur IS SELECT * FROM DEPT; TYPE xxx_nested IS TABLE OF DEPT%ROWTYPE; xxx xxx_nested; BEGIN IF NOT xxx_cur%ISOPEN THEN OPEN xxx_cur; END IF; FETCH xxx_cur BULK COLLECT INTO xxx; CLOSE xxx_cur; FOR i IN xxx.FIRST..xxx.LAST LOOP DBMS_OUTPUT.PUT_LINE(xxx(i).dname); END LOOP; END;
※結果:
ACCOUNTING
RESEARCH
SALES
OPERATIONS
※使用BULK COLLECT一次取出,所以可以馬上關閉游標
※和VARRAY配合使用
DECLARE CURSOR xxx_cur IS SELECT * FROM DEPT; TYPE xxx_varray IS VARRAY(3) OF DEPT%ROWTYPE; xxx xxx_varray; BEGIN IF NOT xxx_cur%ISOPEN THEN OPEN xxx_cur; END IF; FETCH xxx_cur BULK COLLECT INTO xxx LIMIT 3; CLOSE xxx_cur; FOR i IN xxx.FIRST..xxx.LAST LOOP DBMS_OUTPUT.PUT_LINE(xxx(i).dname); END LOOP; END;
※結果:
ACCOUNTING
RESEARCH
SALES
※BULK COLLECT INTO ~~~ LIMIT 可以限制資料量
沒有留言:
張貼留言