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)?
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.
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.
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
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