2016年2月10日 星期三

集合的方法 (PL/SQL 七)

※這一篇雖然是集合的方法,但不見得所有的集合都能用

※CARDINALITY、MEMBER OF、SET

CARDINALITY:取得長度
MEMBER OF:判斷是否是某集合的成員
SET:可去除重覆,也可判斷是否是集合; 集合裡面有重覆不算集合(IS [NOT] A SET)

DECLARE 
    TYPE xxx_nested IS TABLE OF VARCHAR2(10); 
    xxx xxx_nested := xxx_nested('duck', 'tiger', 'duck');
    ooo xxx_nested := xxx_nested();
    str VARCHAR2(10) := 'tiger';
BEGIN
    DBMS_OUTPUT.PUT_LINE(CARDINALITY(xxx));
    DBMS_OUTPUT.PUT_LINE(CARDINALITY(SET(xxx)));
    
    IF xxx IS NOT EMPTY THEN
        DBMS_OUTPUT.PUT_LINE('xxx not empty!');
    END IF;
    
    IF str MEMBER OF xxx THEN
        DBMS_OUTPUT.PUT_LINE('str是xxx的成員!');
    END IF;
    
    IF xxx IS A SET THEN
        DBMS_OUTPUT.PUT_LINE('xxx是集合!');
    END IF;
    
    IF ooo IS A SET THEN
        DBMS_OUTPUT.PUT_LINE('ooo是集合!');
    END IF;
    
    /*
    IF str IS A SET THEN
        DBMS_OUTPUT.PUT_LINE('str是集合!');
    END IF;
    */
END;

※結果:
3
2
xxx not empty!
str是xxx的成員!
ooo是集合!

※xxx之所以不是集合,是因為內容有重覆

※不是集合使用SET判斷會直接錯誤,無法執行



※MULTISET EXCEPT/INTERSECT/UNION、SUBMULTISET


MULTISET EXCEPT:將重覆的元素排除,只留自己(左邊)的
MULTISET INTERSECT:只留重覆的元素
MULTISET UNION:將全部的集合全部合併為一個新集合,包括重覆
SUBMULTISET:判斷左邊的集合是否為右邊的集合,元素的內容必需和比對者的集合<或=才算是比對者的子集合

DECLARE 
    TYPE xxx_nested IS TABLE OF VARCHAR2(10); 
    xxx xxx_nested := xxx_nested('duck', 'tiger');
    ooo xxx_nested := xxx_nested('duck', 'lion');
    judge xxx_nested;
    
    ccc xxx_nested := xxx_nested('duck', 'tiger');
    yyy xxx_nested := xxx_nested('duck', 'tiger', 'elephant');
    zzz xxx_nested := xxx_nested('duck');
BEGIN
    judge := xxx MULTISET EXCEPT ooo;
    FOR i IN judge.FIRST..judge.LAST LOOP
        DBMS_OUTPUT.PUT_LINE('EXCEPT=' || judge(i));
    END LOOP;
    
    judge := xxx MULTISET INTERSECT ooo;
    FOR i IN judge.FIRST..judge.LAST LOOP
        DBMS_OUTPUT.PUT_LINE('INTERSECT=' || judge(i));
    END LOOP;
    
    judge := xxx MULTISET UNION ooo;
    FOR i IN judge.FIRST..judge.LAST LOOP
        DBMS_OUTPUT.PUT_LINE('UNION=' || judge(i));
    END LOOP;
    
    IF ooo SUBMULTISET xxx THEN
        DBMS_OUTPUT.PUT_LINE('ooo是xxx的子集合!');
    END IF;
    
    IF ccc SUBMULTISET xxx THEN
        DBMS_OUTPUT.PUT_LINE('ccc是xxx的子集合!');
    END IF;
    
    IF yyy SUBMULTISET xxx THEN
        DBMS_OUTPUT.PUT_LINE('yyy是xxx的子集合!');
    END IF;
    
    IF zzz SUBMULTISET xxx THEN
        DBMS_OUTPUT.PUT_LINE('zzz是xxx的子集合!');
    END IF;
END;

※結果:
EXCEPT=tiger
INTERSECT=duck
UNION=duck
UNION=tiger
UNION=duck
UNION=lion
ccc是xxx的子集合!
zzz是xxx的子集合!



※DELETE(一個參數)

這裡的刪除,要把COUNT想成沒變動才容易理解
DECLARE 
    TYPE xxx_nested IS TABLE OF VARCHAR2(10); 
    xxx xxx_nested := xxx_nested('a', 'b', 'c', 'd', 'e');
BEGIN
    DBMS_OUTPUT.PUT_LINE('COUNT1=' || xxx.COUNT);
    FOR i IN xxx.FIRST..xxx.LAST LOOP
        DBMS_OUTPUT.PUT_LINE(xxx(i));
    END LOOP;
    
    xxx.DELETE(1);
    
    DBMS_OUTPUT.PUT_LINE(CHR(10) || 'COUNT2=' || xxx.COUNT);
    FOR i IN xxx.FIRST..xxx.LAST LOOP
        DBMS_OUTPUT.PUT_LINE(xxx(i));
    END LOOP;
    
    xxx.DELETE(3);
    
    DBMS_OUTPUT.PUT_LINE(CHR(10) || 'COUNT3=' || xxx.COUNT);
    FOR i IN xxx.FIRST..xxx.LAST LOOP
        IF i = 3 THEN
            CONTINUE;
        END IF;
        DBMS_OUTPUT.PUT_LINE(xxx(i));
    END LOOP;
END;

※結果:
COUNT1=5
a
b
c
d
e

COUNT2=4
b
c
d
e

COUNT3=3
b
d
e

※刪除第一個不需要判斷,但刪其他的不判斷會出錯,因為迴圈一直加1,到刪除的那一筆就會出錯,所以才說要把它想成COUNT不變,才比較好理解



※DELETE(兩個參數)

刪除連續的元素
DECLARE 
    TYPE xxx_nested IS TABLE OF VARCHAR2(10); 
    xxx xxx_nested := xxx_nested('a', 'b', 'c', 'd', 'e');
BEGIN
    DBMS_OUTPUT.PUT_LINE('COUNT1=' || xxx.COUNT);
    FOR i IN xxx.FIRST..xxx.LAST LOOP
        DBMS_OUTPUT.PUT_LINE(xxx(i));
    END LOOP;
    
    xxx.DELETE(2, 4);
    
    DBMS_OUTPUT.PUT_LINE(CHR(10) || 'COUNT2=' || xxx.COUNT);
    FOR i IN xxx.FIRST..xxx.LAST LOOP
        IF i <> 2 AND i != 3 AND i <> 4 THEN
        -- IF i NOT IN(2,3,4) THEN
            DBMS_OUTPUT.PUT_LINE(xxx(i));
        END IF;
    END LOOP;
END;

※結果:
COUNT1=5
a
b
c
d
e

COUNT2=2
a
e

※和刪除(一個參數)一樣,如果是從第一個刪除,不需要判斷


※EXTEND

如果不使用EXTEND,直接給值會出錯,使用了EXTEND可以不給值
DECLARE 
    TYPE xxx_nested IS VARRAY(10) OF VARCHAR2(10); 
    xxx xxx_nested := xxx_nested('a', 'b', 'c');
BEGIN
    DBMS_OUTPUT.PUT_LINE('COUNT1=' || xxx.COUNT);
    xxx.EXTEND(2);
    xxx(5) := 'd';
    DBMS_OUTPUT.PUT_LINE('COUNT2=' || xxx.COUNT);
    
    FOR i IN xxx.FIRST..xxx.LAST LOOP
        DBMS_OUTPUT.PUT_LINE(xxx(i));
    END LOOP;
    
    xxx.EXTEND(2, 2);
    xxx(3) := 'x';
    DBMS_OUTPUT.PUT_LINE('COUNT3=' || xxx.COUNT);
    
    FOR i IN xxx.FIRST..xxx.LAST LOOP
        DBMS_OUTPUT.PUT_LINE(xxx(i));
    END LOOP;
END;

※結果:
COUNT1=3
COUNT2=5
a
b
c

d
COUNT3=7
a
b
x

d
b
b

※不管一或兩個參數,一律都是往下延伸,如果只給一個參數,那延伸的內容是空的,如果給第二個參數,則延伸的內容要看對應的index是什麼值,就全部都是那個值,如上面的index是給2,而2就是「b」,所以最後的兩個延伸出來的內容就全部是「b」


※EXISTS、LIMIT、COUNT

DECLARE 
    TYPE xxx_nested IS VARRAY(5) OF VARCHAR2(10); 
    xxx xxx_nested := xxx_nested('a', 'b', 'c');
BEGIN
    IF xxx.EXISTS(2) THEN
        DBMS_OUTPUT.PUT_LINE('index2存在!');
    END IF;
    
    IF NOT xxx.EXISTS(10) THEN
        DBMS_OUTPUT.PUT_LINE('index10不存在!');
    END IF;
    
    DBMS_OUTPUT.PUT_LINE('集合最大長度=' || xxx.LIMIT);
    DBMS_OUTPUT.PUT_LINE('集合目前長度=' || xxx.COUNT);
END;

※結果:
index2存在!
index10不存在!
集合最大長度=5
集合目前長度=3

※如果是用巢狀表,則集合最大長度是空的



※NEXT、PRIOR

NEXT為取下一個元素; PRIOR為取上一個元素,取不到就是空的
DECLARE 
    TYPE xxx_nested IS TABLE OF VARCHAR2(10) INDEX BY PLS_INTEGER; 
    xxx xxx_nested;
    top NUMBER;
BEGIN
    xxx(10) := 'a';
    xxx(-2) := 'b';
    xxx(1) := 'c';
    xxx(0) := 'd';
    xxx(-10) := 'e';
    
    top := xxx.FIRST;
    /*
    WHILE(xxx.EXISTS(top)) LOOP
        DBMS_OUTPUT.PUT_LINE(top || '=' || xxx(top));
        top := xxx.NEXT(top);
    END LOOP;
    */
    
    FOR i IN xxx.FIRST..xxx.LAST LOOP
        IF i <> top THEN
            CONTINUE;  
        END IF;
    
        IF xxx.EXISTS(top) THEN
            DBMS_OUTPUT.PUT_LINE(i || '=' || xxx(i));
            top := xxx.NEXT(top);
        END IF;
    END LOOP;
    
    DBMS_OUTPUT.PUT_LINE(xxx.NEXT(10));
    DBMS_OUTPUT.PUT_LINE(xxx.NEXT(9));
    DBMS_OUTPUT.PUT_LINE(xxx.PRIOR(10));
    DBMS_OUTPUT.PUT_LINE(xxx.PRIOR(9));
END;

※結果:
-10=e
-2=b
0=d
1=c
10=a

10
1
1



※TRIM

這裡的TRIM和SQL的LTRIM和RTRIM,還有java的trim很不一樣,是刪掉最右邊的意思

DECLARE 
    TYPE xxx_nested IS VARRAY(8) OF VARCHAR2(10); 
    xxx xxx_nested := xxx_nested('a', 'b', 'c', 'd', 'e');
BEGIN
    DBMS_OUTPUT.PUT_LINE('COUNT1=' || xxx.COUNT);
    xxx.TRIM;
    
    DBMS_OUTPUT.PUT_LINE('COUNT2=' || xxx.COUNT);
    FOR i IN xxx.FIRST..xxx.LAST LOOP
        DBMS_OUTPUT.PUT_LINE(xxx(i));
    END LOOP;
    
    xxx.TRIM(2);
    DBMS_OUTPUT.PUT_LINE('COUNT3=' || xxx.COUNT);
    FOR i IN xxx.FIRST..xxx.LAST LOOP
        DBMS_OUTPUT.PUT_LINE(xxx(i));
    END LOOP;
END;

※結果:
COUNT1=5
COUNT2=4
a
b
c
d
COUNT3=2
a
b

沒有留言:

張貼留言