web-dev-qa-db-ja.com

Oracle SQLステートメント内でコレクションを使用する方法

複数のステップでいくつかのデータを収集するOracle関数をコレクション変数に記述し、この非常に単純化した例のように、SELECTクエリ内でそのコレクションデータを使用します。

CREATE OR REPLACE FUNCTION TESTFUNC01 RETURN VARCHAR2 AS 
  -- INT_LIST is declared globally as "TYPE INT_LIST IS TABLE OF INTEGER"
  MyList INT_LIST := INT_LIST();
  MyName VARCHAR2(512);
BEGIN
  MyList.Extend(3);
  MyList(0) := 1;
  MyList(1) := 2;
  MyList(2) := 3;

  SELECT Name INTO MyName
  FROM Item WHERE ItemId NOT IN MyList;
  RETURN MyName;
END TESTFUNC01;

残念ながら「NOT IN MyList」という部分は有効なSQLではありません。これを達成する方法はありますか?

14
blerontin

あなたが探しているのはtable関数です:

CREATE OR REPLACE FUNCTION TESTFUNC01 RETURN VARCHAR2 AS 
  -- INT_LIST is declared globally as "TYPE INT_LIST IS TABLE OF INTEGER"
  MyList INT_LIST := INT_LIST();
  MyName VARCHAR2(512);
BEGIN
  MyList.Extend(3);
  MyList(1) := 1;
  MyList(2) := 2;
  MyList(3) := 3;

  SELECT Name INTO MyName
  FROM Item WHERE ItemId NOT IN (select * from table(MyList));
  RETURN MyName;
END TESTFUNC01;
17
Allan

あなたはこのようにそれを行うことができます:

CREATE OR REPLACE FUNCTION TESTFUNC01 RETURN VARCHAR2 AS 
  -- INT_LIST is declared globally as "TYPE INT_LIST IS TABLE OF INTEGER"
  MyList INT_LIST := INT_LIST();
  MyName VARCHAR2(512);
BEGIN
  MyList.Extend(3);
  MyList(1) := 1;
  MyList(2) := 2;
  MyList(3) := 3;

  SELECT Name INTO MyName
  FROM Item WHERE ItemId NOT IN (SELECT COLUMN_VALUE FROM TABLE(MyList));
  RETURN MyName;
END TESTFUNC01;

リストのインデックスも変更したことに注意してください。 1から始まります(0ではありません)。

6
Codo

Oracle 10を使用している場合は、コレクション拡張機能を使用できます。

CREATE OR REPLACE FUNCTION TESTFUNC01 RETURN VARCHAR2 AS 
  -- INT_LIST is declared globally as "TYPE INT_LIST IS TABLE OF INTEGER"
  MyList INT_LIST := INT_LIST();
  MyName VARCHAR2(512);
BEGIN
  MyList.Extend(3);
  MyList(1) := 1;
  MyList(2) := 2;
  MyList(3) := 3;

  SELECT Name INTO MyName
  FROM Item WHERE ItemId MEMBER OF MyList;
  RETURN MyName;
END TESTFUNC01;

詳細は この投稿 を参照してください

5
pwoodiwiss

-INT_LISTは「TYPE INT_LIST IS TABLE OF INTEGER」としてグローバルに宣言されています

これは、PL/SQL宣言のように見えます。 SELECTステートメントはSQLエンジンを使用します。つまり、SQLでTYPEを宣言する必要があります。

CREATE TYPE INT_LIST AS TABLE OF NUMBER(38,0);
/

次に、それをSELECTステートメントで使用できます。

SELECT Name INTO MyName
FROM Item WHERE ItemId NOT IN (select * from table(MyList));

もちろん、クエリが1行のみを返すこと、またはプログラムがTOO_MANY_ROWS例外を処理することを確認する必要があります。

4
APC