Oracel 遊標Cursor的使用

from: http://www.javaeye.com/topic/79108

     --[4]// Oracle Cursor and OOP Conception    -------------------------------------------------------------------------------------//    --顯示遊標---------------------------------------------------------//    --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;    /       --OOP Conception---------------------------------------------------//    --001   --創建對象類型(相當於C中的結構體,可實現代碼重用機制)---    --**注意:OR REPLACE表示將覆蓋此用戶下的同名對象類型,在不熟悉數據庫結構的時候不要濫用    CREATE OR REPLACE TYPE t_score AS OBJECT    (        java number(5,2),        net  number(5,2)    )    /    --可指定類型名稱直接創建對象表    CREATE TABLE score OF t_score;    --或應用於表中    CREATE TABLE student    (        id    VARCHAR2(4),        name  VARCHAR2(20),        score t_score    );    --爲上表插入數據(利用構造函數)    INSERT INTO student VALUES('s101','張三',t_score(85,76));    --或    INSERT INTO student(id,name,score) VALUES('s102','李四',t_score(80,89));    --查詢指定    SELECT s.score.java FROM student s;  --必須賦予別名    --002   --或者可以創建更爲複雜的對象類型,即類型嵌套    CREATE OR REPLACE TYPE t_stu AS OBJECT    (        id    VARCHAR2(4),        name  VARCHAR2(20),        score t_score    )    /    --應用於表中    CREATE TABLE student    (        stu_base t_stu,        teacher  varchar2(20)    );    --查看錶結構    SET DESC DEPTH ALL;  --指定查看層次,否則只能看到第一層    DESC student;    --插入數據    INSERT INTO student        VALUES(t_stu('s101','zhao',t_score(76,81)),'zhang');    --查詢指定    SELECT s.stu_base.score.java FROM student s WHERE s.stu_base.id = 's101';       --修改對象類型(注:修改對象類型需9i以上版本)------------------------//    --其中INVALIDATE選項使得所有依賴於t_stu類型的對象和表標記爲invalid    --增加屬性address,注:修改後可能引起一些未知的錯誤,所以請不要隨意修改    ALTER TYPE t_stu        ADD ATTRIBUTE address VARCHAR2(50) INVALIDATE;       --刪除類型(注:需按嵌套逐級刪除)    DROP TYPE t_stu;    DROP TYPE t_score;       --繼承-------------------------------------------------------------//    --創建一個不可被繼承的類型    CREATE OR REPLACE TYPE super_TYPE AS OBJECT    (        n NUMBER,        FINAL MEMBER PROCEDURE cannot_override    )    NOT FINAL    /    --繼承時將出錯,可用【SHOW ERROR】語句查看錯誤信息    CREATE OR REPLACE TYPE sub_TYPE UNDER super_TYPE    (        OVERRIDING MEMBER PROCEDURE cannot_override    )    /    --創建一個不可被實例化、不可被繼承的類型    CREATE OR REPLACE TYPE shape AS OBJECT    (        n NUMBER,        NOT INSTANTIABLE MEMBER FUNCTION calculate_area RETURN NUMBER    )    NOT INSTANTIABLE NOT FINAL    /    --實例化改類型將出錯    DECLARE        l_shape shape;    BEGIN        l_shape := shape(2);    END;    /       --嵌套表(表中之表)-------------------------------------------------//    --創建類型,(以下實例將創建一組動物飼養員嵌套表)    CREATE TYPE animal_ty AS OBJECT    (        breed VARCHAR2(25),        name  VARCHAR2(25),        birthdate DATE    );    /    --此類型將用作一個嵌套表的基礎類型    CREATE TYPE animal_nt AS TABLE OF animal_ty;    /    --創建嵌套表    CREATE TABLE breeder    (        breedername VARCHAR2(25),        animals     animal_nt    )    NESTED TABLE animals STORE AS animals_nt_tab;  --animals_nt_tab代表別名    --插入數據    INSERT INTO breeder VALUES('Mary',        animal_nt        (            animal_ty('dog','butch',to_date('2004-3-31','yyyy-mm-dd')),            animal_ty('dog','rover',to_date('2005-8-20','yyyy-mm-dd')),            animal_ty('dog','julio',sysdate)        )    );    INSERT INTO breeder VALUES('Jane',        animal_nt        (            animal_ty('cat','an',to_date('2005-10-12','yyyy-mm-dd')),            animal_ty('cat','jame',to_date('2002-1-23','yyyy-mm-dd')),            animal_ty('cat','killer',to_date('2004-6-2','yyyy-mm-dd'))        )    );    --查詢表中姓名爲Jane所養的動物    SELECT breed,name,birthdate        FROM TABLE(SELECT animals FROM breeder WHERE breedername='Jane');       --可變數組(類似於嵌套表,概念上講它是限定了行集合的嵌套表)----------//    --創建類型(以下實例將創建一組聯繫人嵌套表)    CREATE TYPE comm_info AS OBJECT    (        no        NUMBER(3),    --通訊類型號        comm_TYPE VARCHAR2(20), --通訊類型        comm_no   VARCHAR2(30)  --號碼    )    /    --創建可變數組    CREATE TYPE comm_info_list AS VARRAY(50) OF comm_info;    /    --創建表    CREATE TABLE user_info    (        user_id   NUMBER(6),     --用戶ID        user_name VARCHAR2(20),  --用戶名        user_comm comm_info_list --與用戶聯繫的通訊方式    );    --插入數據    INSERT INTO user_info VALUES(101,'Mary',        comm_info_list(comm_info(1,'手機','13652369888'),                   comm_info(2,'座機','02125689366')));    INSERT INTO user_info VALUES(102,'Tom',        comm_info_list(comm_info(1,'手機','13765235898'),                   comm_info(2,'座機','021-65234789')));    --查詢用戶ID爲101的手機號碼    SELECT comm_type,comm_no        FROM TABLE(SELECT user_comm FROM user_info WHERE user_id = 101)        WHERE no = 1;       --對象表-----------------------------------------------------------//    --創建對象    CREATE OR REPLACE TYPE address AS OBJECT    (        id     NUMBER(4),        street VARCHAR2(50),        state  VARCHAR2(2),        zip    VARCHAR2(11)    )    /    --創建對象表    CREATE TABLE address_table OF address;    --插入數據    INSERT INTO address_table         VALUES(1,'Oracle way','US','90001');    --或使用構造函數    INSERT INTO address_table        VALUES(address(2,'Microsoft way','US','80863'));    --查詢數據    SELECT * FROM address_table;       --VALUE關鍵字:以對象表別名做參數,返回對象實例    SELECT VALUE(a) FROM address_table a;       --REF數據類型:在關係表中關聯對象    CREATE TABLE employee_location    (        empno   NUMBER,        loc_ref REF address SCOPE IS address_table  --此列引用了類型address    );    --查看結構    SET DESC DEPTH ALL;    DESC employee_location;       --REF()函數:將引用對象表中的數據插入    INSERT INTO employee_location        SELECT 101,REF(a)            FROM address_table a WHERE id = 1;    INSERT INTO employee_location        SELECT 102,ref(a)            FROM address_table a WHERE id = 2;    --查詢    --注:用此語句查詢的結果是未解析過的REF數據    SELECT * FROM employee_location    --DEREF():解析REF數據,返回真正指向的實例    SELECT empno,DEREF(loc_ref)        FROM employee_location;       --懸空REF:REF指向的對象實例被刪除了,此時成爲REF懸空(dangling),說明REF指向不存在的實例    DELETE FROM address_table WHERE id = 2;    --查詢    --懸空的REF會返回NULL,使用 IS DANGLING 確定那些REF懸空    SELECT empno FROM employee_location        WHERE loc_ref IS DANGLING;    --清除懸空的REF,將REF更新未NULL    UPDATE employee_location        SET loc_ref = NULL        WHERE loc_ref IS DANGLING;    --再查看:已經將懸空的REF清除    SELECT * FROM employee_location;       --對象視圖---------------------------------------------------------//    --創建表--關係表    CREATE TABLE item    (        item_code VARCHAR2(10),        item_hand NUMBER(10),        item_sode NUMBER(10)    );    --創建對象--使用相同列    CREATE OR REPLACE TYPE item_type AS OBJECT    (        item_code VARCHAR2(10),        item_hand NUMBER(10),        item_sode NUMBER(10)    )    /    --建立對象視圖    CREATE VIEW item_view OF item_type  --OF item_type 說明基於對象        WITH OBJECT OID(item_code)  --WITH OBJECT OID(item_code)明確生成OID        AS        SELECT * FROM item    /    --我們現在可以通過視圖來操作數據    INSERT INTO item_view VALUES(item_type('i101',15,50));       --MAKE_REF()    --關係主表    CREATE TABLE itemfile    (        itemcode   VARCHAR2(5) PRIMARY KEY,        itemdesc   VARCHAR2(20),        p_category VARCHAR2(20),        qty_hand   NUMBER(5),        re_level   NUMBER(5),        max_level  NUMBER(5),        itemrate   NUMBER(9,2)    );    --關係從表    CREATE TABLE order_detail    (        orderno  VARCHAR2(5),        itemcode VARCHAR2(5),        qty_ord  NUMBER(5),        qty_deld NUMBER(5)    );       --PL/SQL表和記錄---------------------------------------------------//    SET SERVEROUTPUT ON;    DECLARE        TYPE rec_emp IS RECORD  --定義記錄        (        no   emp.empno%TYPE,        name emp.ename%TYPE        );           TYPE tab_emp IS TABLE OF rec_emp  --定義 PL/SQL 表            INDEX BY binary_integer;           i NUMBER := 1;        temp_emp tab_emp;  --定義 PL/SQL 表的變量           CURSOR cur_emp IS            SELECT empno,ename FROM emp;    BEGIN        OPEN cur_emp;        FETCH cur_emp INTO temp_emp(i);        LOOP            EXIT WHEN cur_emp%NOTFOUND;            DBMS_OUTPUT.PUT_LINE(temp_emp(i).no || '  ' || temp_emp(i).name);            i := i + 1;            FETCH cur_emp INTO temp_emp(i);        END LOOP;        DBMS_OUTPUT.PUT_LINE('總計打印了 ' || temp_emp.count || ' 條記錄');           CLOSE cur_emp;    END;    /    ----------------------------------------------------------------------------------End
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章