web-dev-qa-db-ja.com

初期化されていないコレクションPL / SQLへの参照

私は受け取ります ORA-06531: Reference to uninitialized collection次の詳細を指定してストアドプロシージャを実行した場合:

ユーザー定義のデータ型:

CREATE OR REPLACE TYPE T IS TABLE OF VARCHAR2;

ストアドプロシージャの定義:

CREATE OR REPLACE PROCEDURE TEST ( u IN T, v OUT T)
IS
BEGIN
  FOR i IN u.FIRST..u.LAST LOOP
    v(i) := u(i);
  END LOOP;
END;

次を使用してプロシージャを呼び出します。

DECLARE
  v_t T;
  u_t T;
BEGIN
  v_t := T();
  v_t.EXTEND(2);

  v_t(1) := "This is test1";
  v_t(2) := "This is test2";
  TEST(v_t, u_t);
END;
9
rohit_agarwal

TESTプロシージャでは、vがOUTパラメータとして宣言されています-これは、プロシージャがプロシージャ内の出力コレクションを初期化する必要があることを意味します(例:v := T();)。 u_tコレクションはプロシージャに渡されないため、u_tを初期化するために呼び出しブロックを変更しても、これは役に立ちません。プロシージャが返すものだけを受け取ります。

コードを次のように変更します。

CREATE OR REPLACE PROCEDURE TEST ( u IN T, v OUT T) IS
  i NUMBER := u.FIRST;
BEGIN
  v := T();
  v.EXTEND(u.COUNT);

  IF i IS NOT NULL THEN
    LOOP
      v(i) := u(i);
      i := u.NEXT(i);
      EXIT WHEN i IS NULL;
    END LOOP;
  END IF;
END TEST;

DECLARE
  v_t T;
  u_t T;
BEGIN
  v_t := T();
  v_t.EXTEND(2);

  v_t(1) := 'This is test1';
  v_t(2) := 'This is test2';

  TEST(v_t, u_t);

  FOR i IN u_t.FIRST..u_t.LAST LOOP
    DBMS_OUTPUT.PUT_LINE(u_t(i));
  END LOOP;
END;

PL/SQLの文字列定数は、二重引用符ではなく単一引用符で囲む必要があることに注意してください。

また、プロシージャと呼び出しブロックで反対の意味を持つ類似の変数名を使用すると、混乱を招くだけです。意味のある名前を使用する習慣を身に付けると、後で混乱を避けることができます。

共有してお楽しみください。

15
Bob Jarvis

私は今日同様の質問がありました、あなたはあなたのu_t変数を初期化する必要があります、チェックしてください this answer

0
zaratustra