2015-10-16 25 views
10

長い話を簡単にするために、私は以下に示すコードについて議論することを提案します。Oracle 12はSQLのローカルコレクション型に問題がありますか?

それを実行している場合:

「PLS: " 'PIPE_TABLE' に間違った番号または呼び出しの引数のヒントの種類PLS-00306"

  • オラクル11コンパイラは

    を上げます-00642:SQL文で許可されていないローカルコレクション型 "

  • オラクル12は、そのような警告で次のパッケージをコンパイルしますが、私たちは、ランタイムでの驚きを持っている

    あるとして、匿名ブロックを実行する - すべてが正常であるが (我々は、パイプpipe_table機能で一部の行があり - それはdoesnの左手と右手のコレクションは同じではありません。「tは

    私たちは、「ORA-22163を取得し、今のはhello;と行のコメントを解除またはそこに任意の手続きへの呼び出しを入れてみましょう、と再び を変更anonumousブロックを実行)影響を与えますタイプ "

質問: Oracle 12ではSQLでローカルコレクション型を使用できますか? の場合、PACKAGE buggy_reportのコードに何が問題なのですか?

CREATE OR REPLACE PACKAGE buggy_report IS 

    SUBTYPE t_id IS NUMBER(10); 
    TYPE t_id_table IS TABLE OF t_id; 

    TYPE t_info_rec IS RECORD (first NUMBER); 
    TYPE t_info_table IS TABLE OF t_info_rec; 
    TYPE t_info_cur IS REF CURSOR RETURN t_info_rec; 

    FUNCTION pipe_table(p t_id_table) RETURN t_info_table PIPELINED; 

    FUNCTION get_cursor RETURN t_info_cur; 

END buggy_report; 
/

CREATE OR REPLACE PACKAGE BODY buggy_report IS 

    FUNCTION pipe_table(p t_id_table) RETURN t_info_table PIPELINED IS 
    l_table t_id_table; 
    BEGIN 
     l_table := p; 
    END; 

    FUNCTION get_cursor RETURN t_info_cur IS 
    l_table t_id_table; 
    l_result t_info_cur; 
    BEGIN 

     OPEN l_result FOR SELECT * FROM TABLE (buggy_report.pipe_table(l_table)); 

     RETURN l_result; 
    END; 
END; 
/

DECLARE 
    l_cur buggy_report.t_info_cur; 
    l_rec l_cur%ROWTYPE; 
    PROCEDURE hello IS BEGIN NULL; END; 
BEGIN 

    l_cur := buggy_report.get_cursor(); 

    -- hello; 

    LOOP 
    FETCH l_cur INTO l_rec; 
    EXIT WHEN l_cur%NOTFOUND; 
    END LOOP; 

    CLOSE l_cur; 

    dbms_output.put_line('success'); 
END; 
/

答えて

0

さらなる実験では、問題はそれが想定されていたより深いことがわかりました。

たとえば、パッケージ内で使用されている要素を変更すると、buggy_reportスクリプトを実行するときに(質問の)ORA-03113: end-of-file on communication channel になることがあります。これは、タイプt_id_tableVARRAYまたはTABLE .. INDEX BY ..に変更して行うことができます。この記事の話題とは異なるさまざまな例外に私たちを導く方法やバリエーションがたくさんあります。

さらに興味深いのは、buggy_reportパッケージ指定のコンパイル時間は、通常約0.05秒かかる場合は、 まで25秒かかることです。私は間違いなく、関数宣言のTYPE t_id_tableパラメータの存在に依存し、40%のインストール事例で "長時間のコンパイル"が起こると言うことができます。したがって、コンパイル中にlocal collection types in SQLの問題が潜在的に発生しているようです。

したがって、Oracle 12.1.0.2には、明らかに、ローカルコレクション型をSQLで使用することのバグがあります。

ORA-22163ORA-03113を得るための最小の例は以下のとおりです。ここでは、質問と同じbuggy_reportパッケージを想定しています。

-- produces 'ORA-03113: end-of-file on communication channel' 
DECLARE 
    l_cur buggy_report.t_info_cur; 

    FUNCTION get_it RETURN buggy_report.t_info_cur IS BEGIN RETURN buggy_report.get_cursor(); END;  
BEGIN 
    l_cur := get_it(); 

    dbms_output.put_line(''); 
END; 
/

-- produces 'ORA-22163: left hand and right hand side collections are not of same type' 
DECLARE 
    l_cur buggy_report.t_info_cur; 

    PROCEDURE hello IS BEGIN NULL; END; 
BEGIN 
    l_cur := buggy_report.get_cursor; 

    -- comment `hello` and exception disappears 
    hello; 

    CLOSE l_cur; 
END; 
/
+0

例には、2つの異常なOracle機能(ローカル収集とパイプライン機能)が含まれています。 「Oracleにはパイプライン機能を持つバグがあります」と言うだけで有効です。私の経験では、パイプライン関数を使用する実装では通常、問題が発生します。 Oracleバグのためか、行単位の処理の制限のために発生します。 –

0

はい、Oracle 12cでは、SQLでローカルコレクション型を使用できます。

ドキュメントDatabase New Features Guideは言う:PL/SQLツーSQLインタフェース

表演算子の両端に許容さ

PL/SQL固有のデータ型は、現在PL/SQLで使用することができますPL/SQLでデータ型が宣言されているコレクションのプログラム。これにより、データ型をPL/SQL連想配列にすることもできます。 (以前のリリースでは、コレクションのデータ型は、スキーマレベルで宣言する必要がありました。)

あなたのコードが機能しない理由しかし、私にはわからない、多分この新機能は、まだバグがあります。

0

私はあなたの例の周りに耳を傾けました。 Oracle 12cがSQL文でPL/SQLコレクションを使用する方法は、互換性のあるSQL型属性を持つサロゲート・スキーマ・オブジェクト型を作成し、問合せでこれらのサロゲート型を使用することです。あなたのケースはバグのようです。私は実行を追跡し、サロゲート型は存在しなければ一度だけ作成されます。したがって、パイプライン関数の実行中に、有効な型は変更も再コンパイルもされません(暗黙の再コンパイルがALTER文を使用して行われるかどうかはわかりません)。そして、pipe_table機能でpパラメータを使用する場合にのみ問題が発生します。 l_table := p;を呼び出さないと、有効なメソッド呼び出しでもコードは正常に実行されます。

+0

"pパラメータを使用すると問題が発生する"とは、 "パラメータpを使用しない"という意味ですか?私はそれを使ってみたいと思っています。 'p'テーブルを反復すると、私は問題に直面しました(おそらくあなたもそれを見つけました)。そしてこのassingnment 'l_table:= p;'はバグを再現する最小限のコードです。今私は2つのことを知っています:1.トリックのない例は、v12.1.0.1で宣言されている "新機能"の最も単純な使い方を示しています。 2.コードはv12.1.0.2でも期待どおりに動作しません。私は、オラクルの開発者が自分のコードを自分のものよりもずっと難しくテストしていると信じたい。それでなぜこれが起こるのですか? – diziaq

+0

いいえ、それは単なる観測に過ぎませんでした。代わりにスキーマタイプを作成することができます( 'CREATE OR REPLACE TYPE t_id_tableはテーブル番号10です')。 – Husqvik

関連する問題