9

これが私が書いたストアドプロシージャです。このプロシージャでは、「p_subjectid」はフロントエンドから渡される数値の配列です。

PROCEDURE getsubjects(p_subjectid subjectid_tab,p_subjects out refCursor) 
       as

       BEGIN

            open p_subjects for select * from empsubject where subject_id in
            (select column_value from table(p_subjectid));
            --select * from table(cast(p_subjectid as packg.subjectid_tab))
      END getsubjects;

これは私が得ているエラーです。

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

別の投稿で見たように、下のコメントに示されているように、テーブル関数内に「cast(p_subjectid as packg.subjectid_tab)」をキャストしようとしました。しかし、別のエラーが発生しますORA-00902: invalid datatype

そして、これが「subjectid_tab」の定義です。

type subjectid_tab is table of number index by binary_integer;

誰かがエラーを教えてもらえますか?私の手順に何か問題がありますか?

4

5 に答える 5

13

ammoQが提案したように、「データベースレベル」でタイプを宣言する必要があります。

CREATE TYPE subjectid_tab AS TABLE OF NUMBER INDEX BY binary_integer;

PL/SQL内でタイプを宣言する代わりに。PL / SQLブロックで型を宣言すると、SQLの「エンジン」では使用できなくなります。

于 2009-09-10T10:55:23.340 に答える
3

Oracleには、SQLとPL/SQLの2つの実行スコープがあります。SELECTSQLスコープで作業している// (etc)ステートメントを使用する場合、Oracle 11g以下では、PL INSERT/ UPDATESQLスコープで定義されている型を参照できません。(注:PL / SQLタイプを参照できるように、Oracle 12はこれを変更しました。)

TYPE subjectid_tab IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;

連想配列であり、PL / SQLスコープでのみ定義できるため、SQL文では使用できません。

必要なのは、以下を使用してSQLスコープでコレクション(連想配列ではない)を定義することです。

CREATE TYPE subjectid_tab IS TABLE OF NUMBER;

(注:コレクションの句は必要ありませんINDEX BY。 )

次に、次のことができます。

OPEN p_subjects FOR
  SELECT *
  FROM   empsubject
  WHERE  subject_id MEMBER OF p_subjectid;

また

OPEN p_subjects FOR
  SELECT *
  FROM   empsubject
  WHERE  subject_id IN ( SELECT COLUMN_VALUE FROM TABLE( p_subjectid ) );
于 2018-04-30T08:43:35.547 に答える
2

私は昨日この問題を抱えていました。

宣言する
  TYPEnumber_tableはTABLEOFNUMBERです。
  result_ids number_table:= number_table();
始める
  /*..私のタイプを正常に使用するコードの束*/

  開いた ?なので
  選択する *
  FROM TABLE(CAST(result_ids AS number_table)); / *ブーム!* /
終わり;

これは、Javaルーチンから呼び出されたときに、前に説明した両方の方法で失敗します。これは、タイプnumber_tableがデータベースから出荷できるよりもエクスポート可能な方法で定義されていないためであることがわかりました。この型は、ルーチンの内部でうまく機能します。しかし、何らかの方法(IN句を含む?!?)でそれを参照するリターナブルレコードセットを実行しようとするとすぐに、定義されていないデータ型を取得します。

したがって、解決策は実際にはCREATE TYPE myschema.number_table IS TABLE OF NUMBER;、ブロックから型宣言を削除し、スキーマレベルの宣言を使用することです。正しいタイプを使用していることを確認するために、スキーマ修飾子を使用してタイプを参照してください。

于 2009-05-27T19:10:05.973 に答える
2

これは良い解決策です。キャストするタイプがpl/sqlブロックのDECLARE部分にある場合、table(cast())を使用することはできません。本当にCREATETYPEmy_type[...]を使用する必要があります。それ以外の場合は、「行をフェッチできません[...]」例外がスローされます。

于 2010-02-18T16:08:53.727 に答える
1

パイプライン化されたクエリの結果をキャストする必要があるので、次のようにします。

パイプライン関数がvarchar2の行タイプを返す場合は、タイプを定義します(たとえば)

CREATE OR REPLACE TYPE char_array_t is VARRAY(32) of varchar2(255);
select * from table(cast(fn(x) as user_type_t ) );

これで動作します。

于 2009-05-26T11:39:57.110 に答える