web-dev-qa-db-fra.com

Comment utiliser une constante de package dans une instruction SQL SELECT?

Comment puis-je utiliser une variable de package dans une simple instruction de requête SELECT dans Oracle?

Quelque chose comme

SELECT * FROM MyTable WHERE TypeId = MyPackage.MY_TYPE

Est-ce possible du tout ou uniquement lors de l'utilisation de PL/SQL (utilisez SELECT dans BEGIN/END)?

41
blerontin

Tu ne peux pas.

Pour qu'une variable de package public soit utilisée dans une instruction SQL, vous devez écrire une fonction wrapper pour exposer la valeur au monde extérieur:

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

Créez une fonction wrapper:

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.

Et maintenant ça marche:

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.

Cordialement,
Rob.

59
Rob van Wijk

Il y a une manière plus générique qui me convient. Vous créez une fonction avec un nom de constante d'entrée (c'est-à-dire schema.package.constantname) et il vous renvoie la valeur constante. Vous utilisez l'exécution immédiate d'un bloc PL/SQL en liant la variable res (voir exemple).

La fonction ressemble à ceci:

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;
/

Vous pouvez ensuite utiliser la constante de n'importe quel package dans n'importe quel SQL, c'est-à-dire comme

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

De cette façon, vous n'avez besoin que d'une seule fonction et vous profitez de l'utilisation des packages.constants existants.

13
Björn

Remarque: J'ai uniquement essayé cela dans Oracle 11g.

J'avais un besoin similaire et j'ai trouvé plus facile de simplement déclarer une fonction (sans le package) pour retourner la valeur souhaitée. Pour les mettre en ddl pour l'importation, n'oubliez pas de séparer chaque déclaration de fonction par le caractère /. Par exemple:

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;
/

Cela vous permet de référencer la fonction comme s'il s'agissait d'une valeur constante (par exemple, vous n'avez même pas besoin des parenthèses).

Par exemple (notez que les méthodes to_char pour montrer que la précision a été préservée): SQL> sélectionnez undefined_int parmi dual;

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

SQL> sélectionnez undefined_string parmi dual;

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

SQL> sélectionnez undefined_double parmi dual;

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

SQL> sélectionnez to_char (undefined_double, '9.999999999999999EEEE') à partir de dual;

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

SQL> sélectionnez to_char (undefined_double, '9.99999999999999999EEEE') à partir de dual;

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

Non, vous n'êtes pas autorisé à le faire. Vous devez fournir une fonction qui renvoie la valeur, puis l'utiliser dans le SQL:

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