2016年2月8日 星期一

集合-陣列、物件 (PL/SQL 五)

※物件

CREATE TYPE xxx_object AS OBJECT (
    p1 varchar2(7),
    p2 number
);
--------------------
DECLARE 
    p xxx_object := xxx_object('default', 0);
BEGIN
    p.p1 := 'ppp';
    DBMS_OUTPUT.PUT_LINE(p.p1);
    DBMS_OUTPUT.PUT_LINE(p.p2);
END;

※物件裡放什麼類型都可以



※陣列


陣列就是定義一組相同的類型,如字串陣列(裡面都是字串)、數字陣列(裡面都是數字)

※宣告陣列

DECLARE 
    TYPE xxx_arrays IS TABLE OF VARCHAR(5) INDEX BY PLS_INTEGER;
    xxx xxx_arrays;
BEGIN
    xxx(-5) := 'a';
    xxx(0) := 'b';
    xxx(3) := 'c';
    
    DBMS_OUTPUT.PUT_LINE('xxx(-5)=' || xxx(-5));
    DBMS_OUTPUT.PUT_LINE('xxx(0)=' || xxx(0));
    DBMS_OUTPUT.PUT_LINE('xxx(3)=' || xxx(3));
    
    --ORA-01403: no data found
    --DBMS_OUTPUT.PUT_LINE('xxx(4)=' || xxx(4));
END;

※TABLE OF後面接類型,而INDEX BY後面接的是索引裡面的類型,要用數字不能用NUMBER(TABLE OF後還是可寫NUMBER),只能用PLS_INTEGER;而字串就寫STRING,官網的5-1表有寫

※如果沒有給index,又想印出來會出錯



※陣列預設值

DECLARE 
    TYPE xxx_arrays IS TABLE OF VARCHAR(5);
    xxx xxx_arrays := xxx_arrays('a','b','c');
BEGIN
    -- DBMS_OUTPUT.PUT_LINE('xxx(1)=' || xxx(1));
    -- DBMS_OUTPUT.PUT_LINE('xxx(2)=' || xxx(2));
    -- DBMS_OUTPUT.PUT_LINE('xxx(3)=' || xxx(3));
     
    FOR i IN xxx.FIRST..xxx.LAST LOOP
        DBMS_OUTPUT.PUT_LINE('xxx(' || i || ')=' || xxx(i));
    END LOOP;
END;

※不能寫「INDEX BY XXX」,預設是從1開始跑,所以可以跑迴圈


※EXISTS

DECLARE 
    TYPE xxx_arrays IS TABLE OF VARCHAR(5) INDEX BY PLS_INTEGER;
    xxx xxx_arrays;
BEGIN
    xxx(0) := 'a';
    xxx(1) := 'b';
    xxx(2) := 'c';
    
    FOR XXX IN 0..2 LOOP
        DBMS_OUTPUT.PUT_LINE(xxx);
    END LOOP;
    
    IF xxx.EXISTS(1) THEN
        DBMS_OUTPUT.PUT_LINE('存在=' || xxx(1));
    ELSE
        DBMS_OUTPUT.PUT_LINE('不存在!');
    END IF;
    
    FOR i IN 0..xxx.COUNT LOOP
        IF xxx.EXISTS(i) THEN
            DBMS_OUTPUT.PUT_LINE(xxx(i));
        END IF;
    END LOOP;
    
    LOOP
        EXIT WHEN NOT xxx.EXISTS(i);
        DBMS_OUTPUT.PUT_LINE(xxx(i));
        i := i + 1;
    END LOOP;
    
    WHILE xxx.EXISTS(i) LOOP
        DBMS_OUTPUT.PUT_LINE(xxx(i));
        i := i + 1;
    END LOOP;
END;

※結果:
0
1
2
存在!b

※使用FOR迴圈取出內容時,要配合EXITS,否則會報「ORA-01403:找不到資料」的錯

※其他方法可在官網找到



※%ROWTYPE

DECLARE 
    TYPE xxx_arrays IS TABLE OF DEPT%ROWTYPE INDEX BY VARCHAR2(5);
    xxx xxx_arrays;
BEGIN
    xxx('dept').dname := 'a';
    xxx('dept').loc := 'b';
    
    IF xxx.EXISTS('dept') THEN
        DBMS_OUTPUT.PUT_LINE('xxx(''dept'').dname=' || xxx('dept').dname);
        DBMS_OUTPUT.PUT_LINE('xxx(''dept'').loc=' || xxx('dept').loc);
        DBMS_OUTPUT.PUT_LINE('xxx(''dept'').deptno=' || xxx('dept').deptno);
    END IF;
END;

※結果:
xxx('dept').dname=a
xxx('dept').loc=b
xxx('dept').deptno=

※陣列裡可以是個%ROWTYPE,如果沒給值印出,不會報錯,是空的



※配合記錄類型一起使用

DECLARE 
    TYPE aaa is record (
        x dept.deptno%type,
        y dept.dname%type,
        z dept.loc%type
    );
    TYPE xxx_arrays IS TABLE OF aaa INDEX BY PLS_INTEGER;
    xxx xxx_arrays;
BEGIN
    xxx(0).y := 'aaa';
    xxx(0).z := 'bbb';
    
    IF xxx.EXISTS(0) THEN
        DBMS_OUTPUT.PUT_LINE('xxx(0).y=' || xxx(0).y);
        DBMS_OUTPUT.PUT_LINE('xxx(0).z=' || xxx(0).z);
        DBMS_OUTPUT.PUT_LINE('xxx(0).x=' || xxx(0).x);
    END IF;
END;

※結果:
xxx(0).y=aaa
xxx(0).z=bbb
xxx(0).x=

※記錄類型必須先宣告,不然陣列抓不到



※配合物件使用

CREATE TYPE xxx_object AS OBJECT (
    p1 varchar2(7),
    p2 number
);
--------------------
DECLARE 
    p xxx_object := xxx_object('default', 0);
    
    TYPE arrs IS TABLE OF xxx_object INDEX BY PLS_INTEGER;
    arr arrs;
BEGIN
    p.p1 := 'ppp';
    DBMS_OUTPUT.PUT_LINE(p.p1);
    DBMS_OUTPUT.PUT_LINE(p.p2);
    
    arr(0) := p;
    FOR i IN arr.first..arr.last LOOP
        DBMS_OUTPUT.PUT_LINE(arr(i).p1);
        DBMS_OUTPUT.PUT_LINE(arr(i).p2);
    END LOOP;
END;




※刪除

declare 
    TYPE xxx_arrays IS TABLE OF VARCHAR(5);
    xxx xxx_arrays := xxx_arrays('a','b','b','c');
begin
    DBMS_OUTPUT.PUT_LINE('xxx=' || xxx.count);
    FOR i IN xxx.FIRST..xxx.LAST LOOP
        IF xxx(i) = 'b' THEN
            DBMS_OUTPUT.PUT_LINE('i=' || i);
            xxx.delete(i);
        END IF;
    END LOOP;
    DBMS_OUTPUT.PUT_LINE('xxx=' || xxx.count);
end;


java 集合的 remove(),還有 javascript 陣列的 splice 在跑循環刪除時,如果有兩個以上連續的、資料一樣的元素,如上面的 b,此時判斷是 b 刪除會有問題,但在 PL/SQL 沒有這個問題

沒有留言:

張貼留言