有没有办法用另一个SYS.ODCINUMBERLIST实例化SYS.ODCINUMBERLIST?

时间:2016-04-28 13:35:56

标签: oracle plsql

有没有办法用另一个SYS.ODCINUMBERLIST实例化SYS.ODCINUMBERLIST?

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;
/

2 个答案:

答案 0 :(得分:2)

如果使用嵌套表而不是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;
/

可以使用MULTISET EXCEPT, INTRESECT and UNION来代替UNION ALL。

如果你想使用varrays:

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;
/

您也可以在这里使用UNION, INTERSECT and MINUS

答案 1 :(得分:2)

没有。 ODCINUMBERLIST is a VARRAY所以某些操作是不允许的。你真正得到的最接近的是克隆一个变量,然后追加另一个变量的所有值:

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

如果列表很大,使用V_GROUP_3.EXTEND(V_GROUP_2.COUNT)进行单个扩展可能会稍微高效,然后跟踪您插入的位置(因为LAST将始终指向数组)。并且@ mottor的变化导致上下文切换通过SQL组合数组也值得关注;你可以通过基准来看看哪个是最好的。

如果您定义自己的类型是嵌套表而不是VARRAY - 在SQL级别或PL / SQL中,取决于您将引用它的方式和位置 - 您可以使用{{3 }}:

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

如果在PL / SQL中声明类型,则无法在SQL操作中使用它;使用SQL级别类型,您可以使用表集合表达式中的变量。

请注意,尽管普通UNION运算符的行为,默认情况下这不会抑制重复;正如文档所示,ALL是隐含的。如果您确实想要删除重复项,可以将其设为UNION DISTINCT