2013-01-24 84 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