2013-01-24 82 views
3

我在PL/SQL包中创建了一个函数,该函数使用定义为数字表的自定义类型。我使用这种类型的目的在与SELECT COLUMN_VALUE指令像这样的SQL查询:自动生成类型

在包类型定义:

type T_IDS is table of my_table.col_id%type; 

在封装主体的过程内的查询:

l_ids_list T_IDS ; 
begin 
select col_ids bulk collect into T_IDS from my_table; 
select sum(t.rec_value) into total_value 
      from my_table t where t.col_id in (
      select column_value from Table(l_ids_list)); 

一切工作正常,当我编译这段代码时,我可以看到在我的schema_name/type部分下生成的新类型。

一旦我将它安装在测试环境中,失败与错误编译:

Error: PLS-00642: local collection types not allowed in SQL statements
Error: PL/SQL: ORA-22905: cannot access rows from a non-nested table item

数据库版本(本地和测试)是完全一样的,11G。有没有办法在DBMS上激活这样的一代?

为例重现:

create table my_table (
col_id number, 
rec_value number 
); 

insert into my_table (col_id, rec_value) values (1,100); 
insert into my_table (col_id, rec_value) values (2,200); 
insert into my_table (col_id, rec_value) values (3,300); 
insert into my_table (col_id, rec_value) values (4,400); 

commit; 

包创建:

create or replace package test_pck as 

type T_IDS is table of my_table.col_id%type; 

procedure test_list; 

end test_pck; 
/

create or replace 
package body test_pck as 

procedure test_list is 
    l_ids_list T_IDS ; 
    total_value number; 
begin 
    select col_id bulk collect into l_ids_list from my_table; 
    select sum(t.rec_value) into total_value 
      from my_table t where t.col_id in (
       select column_value from Table(l_ids_list)); 
end test_list; 
end test_pck; 
/
+1

你的意思是这两个数据库是11.2,即SELECT * FROM V $版本一样?你是在测试中编译过的,还是由Dev的export/import创建的? – 2013-01-24 12:14:18

+0

在检查不同版本之后,不编译的版本是版本11.2.0.3,其中编译版本是11.2.0.1版本。源代码直接在数据库上编译,并且未安装导出文件 –

回答

2

你在做什么是错的。你应该创建SQL类型并且不使用pl/sql类型来访问TABLE函数。

现在至于为什么它实际上在你的开发环境中工作。

无声的pl/sql表创建旨在用于流水线功能,并且已经存在了一段时间,但是您在非流水线功能中使用它,因此这应该失败。但在11g第1版(准确地说是11.1.0.7)中,一个错误意味着它实际上编译了。如果你真的想运行它,虽然你会得到一个错误:

SQL> create package body foo 
    2 as 
    3 
    4 procedure test 
    5  is 
    6    l_ids_list T_IDS ; 
    7    total_value number; 
    8  begin 
    9    select col_id bulk collect into l_ids_list from my_table; 
10    select sum(t.rec_value) into total_value 
11    from my_table t 
12    where t.col_id in (select column_value from Table(l_ids_list)); 
13  end; 
14 end; 
15/

Package body created. 

SQL> exec foo.test; 
BEGIN foo.test; END; 

* 
ERROR at line 1: 
ORA-21700: object does not exist or is marked for delete 
ORA-06512: at "TEST.FOO", line 10 
ORA-06512: at line 1 
SQL> select * from v$version; 

BANNER 
-------------------------------------------------------------------------------- 
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production 
PL/SQL Release 11.2.0.2.0 - Production 
CORE 11.2.0.2.0  Production 
TNS for Linux: Version 11.2.0.2.0 - Production 
NLSRTL Version 11.2.0.2.0 - Production 

现在,甲骨文在11.2.0.3修正了这个错误行为。现在的错误是在编译时抛出:

SQL> create package body foo 
    2 as 
    3 
    4 procedure test 
    5  is 
    6    l_ids_list T_IDS ; 
    7    total_value number; 
    8  begin 
    9    select col_id bulk collect into l_ids_list from my_table; 
10    select sum(t.rec_value) into total_value 
11    from my_table t 
12    where t.col_id in (select column_value from Table(l_ids_list)); 
13  end; 
14 end; 
15/

Warning: Package Body created with compilation errors. 

SQL> show errors 
Errors for PACKAGE BODY FOO: 

LINE/COL ERROR 
-------- ----------------------------------------------------------------- 
10/3  PL/SQL: SQL Statement ignored 
12/48 PL/SQL: ORA-22905: cannot access rows from a non-nested table 
     item 

12/54 PLS-00642: local collection types not allowed in SQL statements 
SQL> select * from v$version; 

BANNER 
-------------------------------------------------------------------------------- 
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production 
PL/SQL Release 11.2.0.3.0 - Production 
CORE 11.2.0.3.0  Production 
TNS for Linux: Version 11.2.0.3.0 - Production 
NLSRTL Version 11.2.0.3.0 - Production 
总之

,与create type和使用创建一个SQL类型来代替:

SQL> create type T_IDS as table of number; 
    2/

Type created. 

SQL> create package body foo 
    2 as 
    3 
    4 procedure test 
    5  is 
    6    l_ids_list T_IDS ; 
    7    total_value number; 
    8  begin 
    9    select col_id bulk collect into l_ids_list from my_table; 
10    select sum(t.rec_value) into total_value 
11    from my_table t 
12    where t.col_id in (select column_value from Table(l_ids_list)); 
13  end; 
14 end; 
15/

Package body created. 

SQL> exec foo.test 

PL/SQL procedure successfully completed. 

SQL> select * from v$version; 

BANNER 
-------------------------------------------------------------------------------- 
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production 
PL/SQL Release 11.2.0.3.0 - Production 
CORE 11.2.0.3.0  Production 
TNS for Linux: Version 11.2.0.3.0 - Production 
NLSRTL Version 11.2.0.3.0 - Production 
+0

确实,SQL类型解决了编译问题。但我不明白的是,11.2.0.1版本生成的全局类型(你称为SQL类型)的结构与我的PL/SQL类型相同,但不是11.2.0.3,这让我想到了配置问题。再次感谢您 –

+2

@HADDARMohamed没有它的配置问题。就像我说的那样,它是11.1.0.7-11.2.0.2中的一个BUG,意味着该类型已生成并且编译成功。两者都不应该发生。如果您有Oracle支持访问权限,请查找“错误9383293 - PL/SQL块中的SQL语句中使用的PL/SQL表类型变量在运行时失败,而不是编译时[ID 9383293.8]” – DazzaL