2016-04-28 1 views
1

Gibt es eine Möglichkeit, SYS.ODCINUMBERLIST mit einer anderen SYS.ODCINUMBERLIST zu instanziieren?Gibt es eine Möglichkeit, SYS.ODCINUMBERLIST mit einer anderen SYS.ODCINUMBERLIST zu instanziieren?

DECLARE 
    V_GROUP_1 SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST(1, 2, 3, 4); -- OK 
    V_GROUP_2 SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST(5, 6, 7, 8); -- OK 
    V_GROUP_3 SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST(V_GROUP_1, V_GROUP_2); -- NOK 
BEGIN 
    FOR X IN V_GROUP_3.FIRST .. V_GROUP_3.LAST LOOP 
    DBMS_OUTPUT.PUT_LINE(V_GROUP_3(X)); 
    END LOOP; 
END; 
/

Antwort

2

Nr. ODCINUMBERLIST is a VARRAY so einige Operationen sind nicht erlaubt. Die nächstgelegene Sie wirklich bekommen kann, ist eine Variable zu klonen und dann alle Werte von der anderen anhängen:

DECLARE 
    V_GROUP_1 SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST(1, 2, 3, 4); 
    V_GROUP_2 SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST(5, 6, 7, 8); -- OK 
    V_GROUP_3 SYS.ODCINUMBERLIST := V_GROUP_1; 
BEGIN 
    FOR i IN 1..V_GROUP_2.COUNT LOOP 
    V_GROUP_3.EXTEND; 
    V_GROUP_3(V_GROUP_3.LAST) := V_GROUP_2(i); 
    END LOOP; 
    FOR X IN V_GROUP_3.FIRST .. V_GROUP_3.LAST LOOP 
    DBMS_OUTPUT.PUT_LINE(V_GROUP_3(X)); 
    END LOOP; 
END; 
/

PL/SQL procedure successfully completed. 

1 
2 
3 
4 
5 
6 
7 
8 

Wenn die Listen groß sind, kann es etwas effizienter sein mit V_GROUP_3.EXTEND(V_GROUP_2.COUNT) eine einzige Erweiterung zu tun und dann Kurs halten wo Sie einfügen (seit LAST wird immer auf das Ende des Arrays zeigen). Und @ mottors Variante, einen Kontextwechsel einzugehen, um die Arrays durch SQL zu kombinieren, lohnt sich ebenfalls; Sie können einen Benchmark erstellen, um zu sehen, welcher der beste ist.

Wenn Sie Ihre eigene Art definieren, die eher eine verschachtelte Tabelle ist als ein VARRAY - entweder auf SQL-Ebene oder in PL/SQL, je nachdem, wie und wo Sie es finden - Sie können the multiset operators verwenden:

CREATE TYPE NUMBERTABLE AS TABLE OF NUMBER 
/

DECLARE 
    V_GROUP_1 NUMBERTABLE := NUMBERTABLE(1, 2, 3, 4); 
    V_GROUP_2 NUMBERTABLE := NUMBERTABLE(5, 6, 7, 8, 4); 
    V_GROUP_3 NUMBERTABLE := V_GROUP_1 MULTISET UNION V_GROUP_2; 
BEGIN 
    FOR X IN V_GROUP_3.FIRST .. V_GROUP_3.LAST LOOP 
    DBMS_OUTPUT.PUT_LINE(V_GROUP_3(X)); 
    END LOOP; 
END; 
/

PL/SQL procedure successfully completed. 

1 
2 
3 
4 
5 
6 
7 
8 

Wenn der Typ in PL/SQL deklariert ist, kann er nicht in SQL-Operationen verwendet werden; Mit einem SQL-Level-Typ können Sie die Variablen in Tabellensammelausdrücken verwenden.

Beachten Sie, dass dies trotz des Verhaltens des normalen UNION-Operators nicht standardmäßig Duplikate unterdrückt; Wie die Dokumentation zeigt, ist die ALL impliziert. Wenn Du Duplikate unterdrücken wolltest, könntest Du UNION DISTINCT machen.

1

Es ist einfacher, wenn Sie verschachtelte Tabellen verwenden nicht VARRAYs:

DECLARE 
    TYPE nested_typ IS TABLE OF NUMBER; 

    nt1 nested_typ := nested_typ (1, 2, 3, 4); 
    nt2 nested_typ := nested_typ (5, 6, 7, 8); 
    nt3 nested_typ := nt1 MULTISET UNION ALL nt2; 
BEGIN 
    FOR X IN nt3.FIRST .. nt3.LAST 
    LOOP 
     DBMS_OUTPUT.PUT_LINE (nt3 (X)); 
    END LOOP; 
END; 
/

Statt UNION ALL ist möglich MULTISET EXCEPT, INTRESECT and UNION zu verwenden.

Und wenn Sie wollen VARRAYs verwenden:

DECLARE 
    V_GROUP_1 SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST (1, 2, 3, 4); -- OK 
    V_GROUP_2 SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST (5, 6, 7, 8); -- OK 
    V_GROUP_3 SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST(); -- NOK 
BEGIN 
    SELECT * 
    BULK COLLECT INTO v_group_3 
    FROM (SELECT * FROM TABLE (V_GROUP_1) 
      UNION ALL 
      SELECT * FROM TABLE (V_GROUP_2)); 

    FOR X IN V_GROUP_3.FIRST .. V_GROUP_3.LAST 
    LOOP 
     DBMS_OUTPUT.PUT_LINE (V_GROUP_3 (X)); 
    END LOOP; 
END; 
/

können Sie hier UNION, INTERSECT and MINUS verwenden.

Verwandte Themen