--顯式遊標---------------------------------------------------------//
--001
DECLARE
CURSOR c1 IS --聲明遊標
SELECT name,address FROM student ORDER BY name;
v_name student.name%TYPE;
v_addr student.address%TYPE;
BEGIN
OPEN c1; --打開遊標
FETCH c1 INTO v_name,v_addr; --第一次定位讀取數據,並保存在變量
--循環讀取數據
WHILE c1%FOUND LOOP
DBMS_OUTPUT.PUT_LINE(TO_CHAR(c1%ROWCOUNT) || ' ' || v_name || ' , ' || v_addr);
FETCH c1 INTO v_name,v_addr;
END LOOP;
DBMS_OUTPUT.PUT_LINE('Total rows is : ' || c1%ROWCOUNT);
CLOSE c1; --關閉遊標
END;
/
--002
DECLARE
CURSOR cur_emp IS
SELECT sal FROM emp WHERE deptno = 20 FOR UPDATE OF sal;
v_sal emp.sal%TYPE;
BEGIN
OPEN cur_emp;
FETCH cur_emp INTO v_sal;
LOOP
EXIT WHEN cur_emp%NOTFOUND;
IF v_sal < 2000 THEN
UPDATE emp SET sal = 2000 WHERE current OF cur_emp; --更新當前數據
END IF;
FETCH cur_emp INTO v_sal;
END LOOP;
DBMS_OUTPUT.PUT_LINE('命令執行完畢');
IF cur_emp%ISOPEN THEN
CLOSE cur_emp;
IF cur_emp%ISOPEN THEN
DBMS_OUTPUT.PUT_LINE('Cursor state : Open');
CLOSE cur_emp;
ELSE
DBMS_OUTPUT.PUT_LINE('Cursor state : Close');
END IF;
END IF;
END;
/
--隱式遊標---------------------------------------------------------//
--不能顯式的使用OPEN、CLOSE和FETCH語句,他會自動完成
DECLARE
no emp.empno%TYPE;
name emp.ename%TYPE;
BEGIN
SELECT empno,ename INTO no,name FROM emp WHERE empno = '7788';
IF SQL%ISOPEN THEN
DBMS_OUTPUT.PUT_LINE('Cursor state : Open');
ELSE
DBMS_OUTPUT.PUT_LINE('Cursor state : Close');
END IF;
DBMS_OUTPUT.PUT_LINE(no || ' ' || name);
DBMS_OUTPUT.PUT_LINE('Return rows : ' || SQL%ROWCOUNT);
EXCEPTION
WHEN CURSOR_ALREADY_OPEN THEN
DBMS_OUTPUT.PUT_LINE('Cursor already open');
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('No data found');
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('Return many rows');
END;
/
--遊標變量(一個遊標變量可以在一個PL\SQL塊中使用多次)---------------------------//
DECLARE
TYPE refcur IS REF CURSOR; --[RETURN TYPE]
cur_emp refcur; --引用遊標
dept emp.deptno%TYPE;
name emp.ename%TYPE;
BEGIN
OPEN cur_emp FOR SELECT deptno FROM emp WHERE empno = '7788';
FETCH cur_emp INTO dept;
DBMS_OUTPUT.PUT_LINE('Dept : ' || dept);
CLOSE cur_emp;
OPEN cur_emp FOR SELECT ename FROM emp WHERE empno = '7788';
FETCH cur_emp INTO name;
DBMS_OUTPUT.PUT_LINE('Name : ' || name);
CLOSE cur_emp;
END;
/
--遊標在三種循環中的使用-------------------------------------------//
--001--Loop
DECLARE
CURSOR cur_emp IS
SELECT ename FROM emp;
v_name emp.ename%TYPE;
BEGIN
OPEN cur_emp;
FETCH cur_emp INTO v_name;
LOOP
EXIT WHEN cur_emp%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Name is : ' || v_name);
FETCH cur_emp INTO v_name;
END LOOP;
DBMS_OUTPUT.PUT_LINE('Return rows : ' || cur_emp%ROWCOUNT);
CLOSE cur_emp;
END;
/
--002--While
DECLARE
CURSOR cur_emp IS
SELECT ename FROM emp;
v_name emp.ename%TYPE;
BEGIN
OPEN cur_emp;
FETCH cur_emp INTO v_name;
WHILE cur_emp%FOUND LOOP
DBMS_OUTPUT.PUT_LINE('Name is : ' || v_name);
FETCH cur_emp INTO v_name;
END LOOP;
DBMS_OUTPUT.PUT_LINE('Return rows : ' || cur_emp%ROWCOUNT);
CLOSE cur_emp;
END;
/
--003--For
--注:在使用 FOR 循環時,不能顯式的使用 open、colse 和 FETCH 語句,他會自動完成
DECLARE
rows number := 0;
CURSOR cur_emp IS
SELECT ename FROM emp;
BEGIN
FOR v_emp in cur_emp LOOP
DBMS_OUTPUT.PUT_LINE('name is : ' || v_emp.ename);
rows := rows + 1;
END LOOP;
DBMS_OUTPUT.PUT_LINE('Return rows : ' || rows);
END;
/