2017-09-15 563 views
1

我想使用here提出的方法对Oracle PL/SQL集合(关联数组)进行排序。我修改了链接页面的示例,以便使用关联数组,但我想我遇到了一些投射问题。Oracle CAST MULTISET ORA-00902:无效的数据类型

这是我的代码:

DECLARE 

    TYPE TABLE_TYPE IS TABLE OF NUMBER INDEX BY VARCHAR2(10); 
    table_in TABLE_TYPE; 
    table_out TABLE_TYPE; 

BEGIN 

    -- 1. Populating the collection with random numbers between 1 and 50 
    FOR i IN 1..9 LOOP 

     SELECT ROUND(DBMS_RANDOM.VALUE(1,50)) 
     INTO table_in('key-'||i) 
     FROM DUAL;  

    END LOOP; 

    -- 2. Trying to order the collection -> throws ORA-00902: invalid datatype 
    SELECT CAST (MULTISET(
     SELECT * FROM TABLE(table_in) 
     ORDER BY 2 
    ) AS TABLE_TYPE 
    ) 
    INTO table_out 
    FROM DUAL; 

END; 

我在做什么错?

+0

你不能在关联数组上使用'MULTISET'。 –

回答

0

不能使用associative arrayselect一个table,因为那个时候正在SQL EngineSQL Engine不知道什么是associative arraySQL Engine可以只适用于Table Type,你不需要先selectselect from dual) ,您可以通过pl/sql engine做它,改变它这样

.................... 
TYPE NumbersTableType IS TABLE OF NUMBER; -- it must be in global types, not in your local package 
.................... 

DECLARE 

    table_in NumbersTableType := NumbersTableType(); 
    table_out NumbersTableType; 

BEGIN 

    -- 1. Populating the collection with random numbers between 1 and 50 
    FOR i IN 1..9 LOOP 
     table_in.Extend; 
     table_in(i):=ROUND(DBMS_RANDOM.VALUE(1,50)); 
    END LOOP; 

    SELECT CAST (MULTISET(
     SELECT * FROM TABLE(table_in) 
     ORDER BY 1 
    ) AS NumbersTableType 
    ) 
    INTO table_out 
    FROM DUAL; 

END; 
+0

非常感谢!除了关于全局范围的问题(你肯定是对的),是否有办法使用由VARCHAR索引的全局关联数组(如我的原始代码)而不是数字集合(如在你的解决方案中)? – serkelion

+0

不,应该只有表类型 – Vecchiasignora

+0

@serkelion自12c以来,可以使用包表规范中定义的关联数组的表表达式。 – 0xdb

0

为了完整,我会在这里报告我用12C之前订购的Oracle版本集合(由VARCHAR指数)琐碎的解决方法的缘故。该解决方案只是使用自定义Table类型替换关联数组集合(为了使其对于SQL引擎可见)。

CREATE OR REPLACE TYPE MY_TABLE_TYPE_OBJ AS OBJECT (
    THE_KEY VARCHAR2(10), 
    THE_VALUE NUMBER 
); 
/
CREATE OR REPLACE TYPE MY_TABLE_TYPE IS TABLE OF MY_TABLE_TYPE_OBJ; 
/

DECLARE 

    my_key VARCHAR2(10); 
    table_in MY_TABLE_TYPE := MY_TABLE_TYPE(); 
    table_out MY_TABLE_TYPE := MY_TABLE_TYPE(); 

BEGIN 

    -- Creating an unsorted collection 
    FOR i IN 1..9 LOOP 
     table_in.EXTEND; 
     table_in(i) := MY_TABLE_TYPE_OBJ(
     'key-'||i, 
     ROUND(DBMS_RANDOM.VALUE(1,50)) 
    ); 
    END LOOP; 

    -- Sorting the collection 
    SELECT CAST (MULTISET(
     SELECT * FROM TABLE(table_in) 
     ORDER BY 2 
    ) AS MY_TABLE_TYPE 
    ) 
    INTO table_out 
    FROM DUAL; 

END; 

希望这会有所帮助。