2

试图将 SQL 类型集合转换为 PLSQL 类型。

-- create an SQL type
create or replace type arrayforvarchar as table of varchar2(30);
/

检查下面的匿名块:

declare
    type arrayforvarcharplsql is table of varchar2(30);
    var_plsql_array arrayforvarcharplsql;
    var_sql_array arrayforvarchar := arrayforvarchar();
begin
    select cola
    bulk collect into var_plsql_array
    FROM (
        select 'X' as cola from dual
        union all
        select 'Y' as cola from dual
        );
end;
/

除了使用循环之外,如何分配 to 的值var_plsql_arrayvar_sql_array

无论如何,简单的分配是行不通的。

4

2 回答 2

4

不是我能找到:

使用简单的赋值不起作用,因为数组有不同的类型:

declare
    type arrayforvarcharplsql is table of varchar2(30);
    var_plsql_array arrayforvarcharplsql;
    var_sql_array arrayforvarchar;
begin
    var_plsql_array := arrayforvarcharplsql( 'X', 'Y' );
    
    var_sql_array := var_plsql_array;
end;
/

输出:

ORA-06550: line 8, column 22:
PLS-00382: expression is of wrong type
ORA-06550: line 8, column 5:
PL/SQL: Statement ignored

尝试使用CAST在 PL/SQL 范围内不起作用,因为它只在 SQL 范围内起作用:

declare
    type arrayforvarcharplsql is table of varchar2(30);
    var_plsql_array arrayforvarcharplsql;
    var_sql_array arrayforvarchar;
begin
    var_plsql_array := arrayforvarcharplsql( 'X', 'Y' );
    
    var_sql_array := CAST( var_plsql_array AS arrayforvarchar );
end;
/

输出:

ORA-06550: line 8, column 22:
PLS-00204: function or pseudo-column '' may be used inside a SQL statement only
ORA-06550: line 8, column 5:
PL/SQL: Statement ignored

尝试将 PL/SQL 集合传递到 SQL 范围内以便能够使用CAST不起作用,因为 PL/SQL 集合不能在 SQL 范围内使用:

declare
    type arrayforvarcharplsql is table of varchar2(30);
    var_plsql_array arrayforvarcharplsql;
    var_sql_array arrayforvarchar;
begin
    var_plsql_array := arrayforvarcharplsql( 'X', 'Y' );
    
    SELECT CAST( var_plsql_array AS arrayforvarchar )
    INTO   var_sql_array
    FROM   DUAL;
end;
/

输出:

ORA-06550: line 8, column 18:
PLS-00642: local collection types not allowed in SQL statements

尝试将 PL/SQL 集合传递到 SQL 范围内的表集合表达式中并使用BULK COLLECT与前面相同的原因不起作用:

declare
    type arrayforvarcharplsql is table of varchar2(30);
    var_plsql_array arrayforvarcharplsql;
    var_sql_array arrayforvarchar;
begin
    var_plsql_array := arrayforvarcharplsql( 'X', 'Y' );
    
    SELECT COLUMN_VALUE
    BULK COLLECT INTO var_sql_array
    FROM   TABLE( var_plsql_array );
end;
/

输出:

ORA-06550: line 10, column 19:
PLS-00642: local collection types not allowed in SQL statements
ORA-06550: line 10, column 12:
PL/SQL: ORA-22905: cannot access rows from a non-nested table item
ORA-06550: line 8, column 5:
PL/SQL: SQL Statement ignored

但是,使用循环并单独分配值确实有效:

declare
    type arrayforvarcharplsql is table of varchar2(30);
    var_plsql_array arrayforvarcharplsql;
    var_sql_array arrayforvarchar;
begin
    var_plsql_array := arrayforvarcharplsql( 'X', 'Y' );
    
    var_sql_array := arrayforvarchar();
    var_sql_array.EXTEND( var_plsql_array.COUNT );
    FOR i IN 1 .. var_plsql_array.COUNT LOOP
      var_sql_array(i) := var_plsql_array(i);
    END LOOP;
end;
/

db<>在这里摆弄

于 2020-09-25T13:37:21.200 回答
4

不,您不能在不使用循环的情况下将一种集合类型的值分配给另一种集合类型。请参阅为集合变量赋值

数据类型兼容性
只有当它们具有相同的数据类型时,您才能将集合分配给集合变量。
拥有相同的元素类型是不够的。

即使在 PL/SQL 中声明了这些集合中的任何一个,它也不起作用:

declare 
    type t1 is table of int;
    type t2 is table of int;
    a t1 := t1 (1);
    b t2;
begin b := a;
end;
/
ORA-06550: line 6, column 12:
PLS-00382: expression is of wrong type

没有像CAST将一种类型的集合转换为另一种类型的集合这样的内部函数。虽然您可以使用自己的函数来隐藏循环。可重现的例子:

create or replace type arrsql as table of varchar2 (30);
/
var rc refcursor
declare
    type arrpls is table of varchar2(30);
    source arrpls := arrpls ('aaa','bbb','ccc');
    target arrsql;
    function cast (s arrpls, astypeof arrsql) return arrsql is
        t arrsql := arrsql ();
    begin
        t.extend (s.count); 
        for i in 1..s.count loop t(i) := s(i); end loop;
        return t;
    end; 
begin
    target := cast (source, astypeof=>target);
    open :rc for select * from table (target);
end;
/

Result Sequence
------------------------------
aaa
bbb
ccc
于 2020-09-26T13:24:42.883 回答