※顯式游標的修改
DECLARE CURSOR xxx_cur IS SELECT * FROM EMP; BEGIN FOR xxx_emp IN xxx_cur LOOP IF xxx_emp.deptno = 10 THEN IF xxx_emp.sal * 1.2 < 3000 THEN UPDATE EMP SET SAL = xxx_emp.sal * 1.2 WHERE EMPNO = xxx_emp.empno; END IF; ELSIF xxx_emp.deptno = 20 THEN IF xxx_emp.sal * 1.4 < 3000 THEN UPDATE EMP SET SAL = xxx_emp.sal * 1.4 WHERE EMPNO = xxx_emp.empno; END IF; END IF; END LOOP; COMMIT; DBMS_OUTPUT.PUT_LINE('修改成功'); EXCEPTION WHEN others THEN DBMS_OUTPUT.PUT_LINE('SQLCODE=' || SQLCODE); DBMS_OUTPUT.PUT_LINE('SQLERRM=' || SQLERRM); ROLLBACK; END;
※看起來沒什麼難度
※行級鎖定
就是再撈資料時,將table的行鎖起來,讓別人不能用,以免被人修改或刪除了,Hibernate把它變成悲觀鎖了如:CURSOR xxx_cur IS SELECT * FROM EMP WHERE DEPTNO = 10 FOR UPDATE
.FOR UPDATE:鎖起來不讓別人用
.FOR UPDATE NOWAIT:因為有可能要用時已經被人鎖起來了,如果不加NOWAIT,就會一直等到釋放了才換自己做事;但加了就不等了,直接回來
.FOR UPDATE OF 欄位1, 欄位2...:在join很多表時,如果只使用FOR UPDATE不一定能更新成功,如果要確定能更新就必需要加上OF欄位名
DECLARE CURSOR xxx_cur IS SELECT * FROM DEPT WHERE DEPTNO = 10 FOR UPDATE OF LOC; BEGIN FOR xxx_dept IN xxx_cur LOOP UPDATE DEPT SET DNAME = 'xxx' WHERE CURRENT OF xxx_cur; -- DELETE FORM DEPT WHERE CURRENT OF xxx_cur; DBMS_OUTPUT.PUT_LINE(xxx_cur%ROWCOUNT); END LOOP; COMMIT; DBMS_OUTPUT.PUT_LINE('修改/刪除成功'); EXCEPTION WHEN others THEN DBMS_OUTPUT.PUT_LINE('SQLCODE=' || SQLCODE); DBMS_OUTPUT.PUT_LINE('SQLERRM=' || SQLERRM); ROLLBACK; END;
※使用「CURRENT OF游標」時,一定要有FOR UPDATE,它的功能是定位目前的資料行
※動態游標
動態的指定內容,看第二個範例就懂了※宣告動態游標
DECLARE TYPE xxx_dynamic IS REF CURSOR; -- RETURN DEPT%ROWTYPE; xxx xxx_dynamic; xxx_dept DEPT%ROWTYPE; BEGIN OPEN xxx FOR SELECT * FROM DEPT; LOOP FETCH xxx INTO xxx_dept; EXIT WHEN xxx%NOTFOUND; DBMS_OUTPUT.PUT_LINE(xxx_dept.dname); END LOOP; CLOSE xxx; END;
※因為FETCH是INTO到DEPT%ROWTYPE,所以註解可加可不加,不加的又叫「弱游標」
※弱游標的好處
DECLARE -- xxx SYS_REFCURSOR; TYPE xxx_dynamic IS REF CURSOR; xxx xxx_dynamic; xxx_dept DEPT%ROWTYPE; xxx_emp EMP%ROWTYPE; BEGIN OPEN xxx FOR SELECT * FROM DEPT; LOOP FETCH xxx INTO xxx_dept; EXIT WHEN xxx%NOTFOUND; DBMS_OUTPUT.PUT_LINE(xxx_dept.dname); END LOOP; CLOSE xxx; DBMS_OUTPUT.PUT_LINE(''); OPEN xxx FOR SELECT * FROM EMP WHERE DEPTNO = 10; LOOP FETCH xxx INTO xxx_emp; EXIT WHEN xxx%NOTFOUND; DBMS_OUTPUT.PUT_LINE(xxx_emp.ename); END LOOP; CLOSE xxx; END;
※結果:
ACCOUNTING
RESEARCH
SALES
OPERATIONS
CLARK
KING
MILLER
※因為是弱游標,所以兩次的FETCH~INTO不一樣,但是還是OK的,所以才叫動態游標
※在Oracle9i提供了一個寫法來代替弱游標,就是註解那一行,只要SYS_REFCURSOR就可以取代TYPE和xxx dynamic那兩行了
沒有留言:
張貼留言