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 セクションの下に新しい型が生成されていることがわかります。

これをテスト環境にインストールすると、エラーでコンパイルに失敗します:

エラー: PLS-00642: ローカル コレクション タイプは SQL ステートメントでは許可されていません
エラー: PL/SQL: ORA-22905: ネストされていないテーブル アイテムの行にアクセスできません

データベースのバージョン (ローカルとテスト) はまったく同じ 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;
/
4

1 に答える 1

2

あなたがしていることは間違っています。関数にアクセスするために pl/sql 型を使用するのではなく、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

現在、Oracle は 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

つまり、SQL タイプを作成し、create type代わりにそれを使用します。

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
于 2013-01-24T13:08:58.113 に答える