web-dev-qa-db-ja.com

SQL SELECTステートメントでパッケージ定数を使用する方法は?

Oracleの単純なSELECTクエリステートメントでパッケージ変数を使用するにはどうすればよいですか?

何かのようなもの

SELECT * FROM MyTable WHERE TypeId = MyPackage.MY_TYPE

PL/SQLを使用する場合、またはPL/SQLを使用する場合にのみ可能ですか(BEGIN/END内でSELECTを使用してください)?

41
blerontin

できません。

パブリックパッケージ変数をSQLステートメントで使用するには、値を外部に公開するラッパー関数を作成する必要があります。

SQL> create package my_constants_pkg
  2  as
  3    max_number constant number(2) := 42;
  4  end my_constants_pkg;
  5  /

Package created.

SQL> with t as
  2  ( select 10 x from dual union all
  3    select 50 from dual
  4  )
  5  select x
  6    from t
  7   where x < my_constants_pkg.max_number
  8  /
 where x < my_constants_pkg.max_number
           *
ERROR at line 7:
ORA-06553: PLS-221: 'MAX_NUMBER' is not a procedure or is undefined

ラッパー関数を作成します。

SQL> create or replace package my_constants_pkg
  2  as
  3    function max_number return number;
  4  end my_constants_pkg;
  5  /

Package created.

SQL> create package body my_constants_pkg
  2  as
  3    cn_max_number constant number(2) := 42
  4    ;
  5    function max_number return number
  6    is
  7    begin
  8      return cn_max_number;
  9    end max_number
 10    ;
 11  end my_constants_pkg;
 12  /

Package body created.

そして今、それは動作します:

SQL> with t as
  2  ( select 10 x from dual union all
  3    select 50 from dual
  4  )
  5  select x
  6    from t
  7   where x < my_constants_pkg.max_number()
  8  /

         X
----------
        10

1 row selected.

よろしく、
ロブ。

59
Rob van Wijk

私にとってうまく機能するより一般的な方法があります。入力定数名(つまりschema.package.constantname)を使用して関数を作成すると、定数値が返されます。 res変数をバインドすることにより、PL/SQLブロックの即時実行を利用します(例を参照)。

関数は次のようになります。

CREATE OR REPLACE FUNCTION GETCONSTANTVALUE (i_constant IN VARCHAR2)  RETURN NUMBER deterministic AS

   res number; 
BEGIN

   execute immediate 'begin :res := '||i_constant||'; end;' using out res;     
   RETURN res;

END;
/

その後、任意のSQLで任意のパッケージの定数を使用できます。

select GETCONSTANTVALUE('PKGGLOBALCONSTANTS.constantname') from dual;

このように、必要な関数は1つだけで、既存のpackages.constantsを使用することを利用できます。

13
Björn

注:これはOracle 11gでのみ試しました。

同様のニーズがあり、目的の値を返す関数を(パッケージなしで)単純に宣言する方が簡単であることがわかりました。これらをインポート用のddlに入れるには、各関数宣言を/文字で区切ることを忘れないでください。例えば:

CREATE OR REPLACE FUNCTION UNDEFINED_INT RETURN NUMBER AS BEGIN RETURN 2147483646; END;
/
CREATE OR REPLACE FUNCTION UNDEFINED_SHORT RETURN NUMBER AS BEGIN RETURN 32766; END;
/
CREATE OR REPLACE FUNCTION UNDEFINED_LONG RETURN NUMBER  AS BEGIN RETURN 223372036854775806; END;
/
CREATE OR REPLACE FUNCTION UNDEFINED_FLOAT RETURN FLOAT  AS BEGIN RETURN .4028233E38; END;
/
CREATE OR REPLACE FUNCTION UNDEFINED_DOUBLE RETURN BINARY_DOUBLE  AS BEGIN RETURN to_binary_double('1.7976931348623155E308'); END;
/
CREATE OR REPLACE FUNCTION UNDEFINED_STRING RETURN VARCHAR AS BEGIN RETURN '?'; END;
/

これにより、定数値であるかのように関数を参照できます(たとえば、括弧も必要ありません)。

たとえば(精度が保持されていることを示すto_charメソッドに注意してください):SQL> select undefined_int from dual;

UNDEFINED_INT
-------------
   2147483646

SQL>デュアルからundefined_stringを選択します。

UNDEFINED_STRING
--------------------------------------------------------------------------------
?

SQL>デュアルからundefined_doubleを選択します。

UNDEFINED_DOUBLE
----------------
      1.798E+308

SQL>デュアルからto_char(undefined_double、 '9.999999999999999EEEE')を選択します。

TO_CHAR(UNDEFINED_DOUBL
-----------------------
 1.797693134862316E+308

SQL>デュアルからto_char(undefined_double、 '9.99999999999999999EEEE')を選択します。

TO_CHAR(UNDEFINED_DOUBLE,
-------------------------
 1.79769313486231550E+308
7
Nathaniel Mills

いいえ、許可されていません。値を返す関数を提供し、それをSQLで使用する必要があります。

SELECT * FROM MyTable WHERE TypeId = MyPackage.FUN_MY_TYPE
4
Tony Andrews