2013-10-06 85 views
7
DECLARE 
TYPE record_AB IS RECORD 
    (
     AA    VARCHAR2 (16 BYTE), 
     BB VARCHAR2 (16 BYTE) 
    ); 

    TYPE type_tab_AB IS TABLE OF record_AB 
         INDEX BY BINARY_INTEGER; 

    tab_AB type_tab_AB; 

    BEGIN 
    SELECT * 
    BULK COLLECT INTO tab_AB FROM... 
    .. 
    SELECT * FROM TABLE (tab_AB) ; 

SELECT文からTABLE文に移ると、「ORA-22905:ネストしていない表項目から行にアクセスできません」というメッセージが表示されます。ORA-22905 - SELECT文を使用して表タイプを問い合せる場合

PLSQL内のテーブルタイプを照会することは可能ですか?

+0

これはもっと文脈が必要だと思います。このエラーを示す_complete_ minimalの例を投稿できますか?あなたがなぜこの変数を何に選択しているのかを知るには、プロシージャ内の複数のレコードで 'tab_AB'を設定しなければなりません。 – Ben

答えて

23

PL/SQLのテーブル・タイプを照会することが可能であるが、そのタイプのスキーマ・レベル、PL/SQLの即ち外側に宣言されているだけネストした表およびVARRAY。

エラー

ORA-22905: cannot access rows from a non-nested table item

はサポートされていないテーブルタイプから照会しようとしていることを意味します。タイプtype_tab_ABは、INDEX BY BINARY_INTEGER句のために連想配列です。 INDEX BY BINARY_INTEGER句を削除して、type_tab_ABをネストした表の型にします。 (Varrayもここで動作しますが、期待する行数の上限がわからないかぎり使用しないでください。varray型を宣言するときは、要素の最大数を指定する必要があります。そのような制限はありません)。

この変更を行った後も、コードが動作しない可能性があります。あなたは(あなたがいない場合一番下の注を参照)を得ることが次のエラーがある

PLS-00642: local collection types not allowed in SQL statements

これあなたに選択されているタイプは、PL/SQL内で宣言されているためです。 CREATE TYPE ...を使用して、type_tab_ABおよびrecord_ABをPL/SQL以外で宣言する必要があります。

次の問題は、キーワードRECORDが原因で発生します。レコード・タイプは、PL/SQL内でのみ作成することができます。they cannot be created at schema level。これを修正するにはRECORDOBJECTに変更してください。

あなたが遭遇する最後の問題は、SELECT t.AA, t.BB BULK COLLECT INTO tab_AB FROM ...ステートメントです。現状では、このクエリを使用すると、次のエラーを与える:

PL/SQL: ORA-00947: not enough values

あなたは、各行から2項目を選択しているし、一括挿入にデータをに1つのテーブルのみを提供しています。オラクルでは、2つのアイテムをrecord_ABタイプに入れる必要があることを理解できません。クエリをSELECT record_AB(t.AA, t.BB) BULK COLLECT INTO tab_AB FROM ...に変更すると、これを簡単に修正できます。

これらの変更をまとめて問題を解決する必要があります。ここではいくつかのテストデータとテストテーブルを作成し、それがテーブルタイプを照会することができることを確認し、完全なSQL * Plusスクリプトです:

CREATE TABLE some_table (AA VARCHAR2(16 BYTE), BB VARCHAR2(16 BYTE)); 

INSERT INTO some_table (AA, BB) VALUES ('aa 1', 'bb 1'); 
INSERT INTO some_table (AA, BB) VALUES ('aaaaaaaaaa 2', 'b 2'); 
INSERT INTO some_table (AA, BB) VALUES ('aaaaa 3', 'bbbbbbbbbbbbbb 3'); 
COMMIT; 

VARIABLE curs REFCURSOR; 

CREATE OR REPLACE TYPE record_AB AS OBJECT 
    (
     AA VARCHAR2 (16 BYTE), 
     BB VARCHAR2 (16 BYTE) 
    ); 
/

CREATE OR REPLACE TYPE type_tab_AB IS TABLE OF record_AB; 
/

DECLARE 
    tab_AB type_tab_AB; 
BEGIN 
    SELECT record_AB(t.AA, t.BB) 
    BULK COLLECT INTO tab_AB 
    FROM some_table t; 

    OPEN :curs FOR SELECT * FROM TABLE (tab_AB) ; 
END; 
/

PRINT :curs 

私はカーソルにtab_ABの内容をINGのSELECTの結果を入れています、その内容をリストするためにSQL * Plusカーソル変数を使用しました。次のようにメッセージをと「正常に完了したPL/SQLプロシージャ」、「作成タイプ」のすべての後、私はOracleの11グラムXEでスクリプトを実行したときに私が得る出力は、次のとおりです。簡単にするために:

AA    BB 
---------------- ---------------- 
aa 1    bb 1 
aaaaaaaaaa 2  b 2 
aaaaa 3   bbbbbbbbbbbbbb 3 

NOTE質問者がOracle 11またはそれ以前のバージョンを使用していると仮定しています。 Oracle 12では、SQL問合せでPL/SQLで宣言された型を使用することが許可されているため、PLS-00642エラーが発生することはありません。まだ私はOracle 12をまだ使用していないので、私の答えの他の変更がOracle 12に必要かもしれないとは言いません。

+1

'ネストされたテーブルのみ'ネストしたテーブルではありません。変数配列SQLデータ型でも 'table'演算子を使うことができます。 –

+1

@NicholasKrasnov:ありがとう、私はそれを知らなかった。私はVARRAYについて言及するために私の答えを更新しました。以前はVARRAYを使っていたとは言えませんが、ここではうまく動作するとは思えません。そのOracleエラーメッセージは、ネストされたテーブルだけが 'TABLE'演算子で動作することを暗示していることは残念です。 –

+0

私はOracle 12と11の両方を使用していますが、仕様レベルで宣言されている表の型から選択しようとすると、アプリケーションを12から11に移植するこのエラーが発生しました。ありがとう! –

2

pl/sqlブロック内で作成された型を照会することはできません。あなたはSQLプロンプトでそれを作成する必要がありますし、あなたはそれをクエリすることができます。 exmaple下記を参照:

[email protected]> CREATE OR REPLACE TYPE emp_type AS OBJECT 
    2 (id NUMBER, 
    3  name VARCHAR2(20)); 
    4/

Type created. 

[email protected]> CREATE OR REPLACE TYPE emp_tab AS TABLE OF emp_type; 
    2/

Type created. 

[email protected]> VARIABLE g_ref REFCURSOR 
[email protected]> DECLARE 
    2 employees emp_tab := emp_tab(); 
    3 BEGIN 
    4 employees.EXTEND(2); 
    5 employees(1) := emp_type (1, 'name1'); 
    6 employees(2) := emp_type (2, 'name2'); 
    7 OPEN :g_ref FOR 
    8 SELECT * FROM TABLE (CAST (employees AS emp_tab)); 
    9 END; 
10/