2011-03-03 14 views

Respuesta

47

No puede.

Para una variable de paquete pública para ser utilizado en una sentencia SQL, usted tiene que escribir una función de contenedor para exponer el valor con el mundo exterior:

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 

Crear una función de contenedor:

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. 

Y ahora funciona:

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. 

Saludos,
Rob.

+5

Debe marcar la función de recorrido 'deterministic', u Oracle lo llamará innecesariamente cada vez que necesite' max_number' – Crack

3

No, no se te permite hacer eso. Debería proporcionar una función que devuelva el valor y luego usar eso en el SQL:

SELECT * FROM MyTable WHERE TypeId = MyPackage.FUN_MY_TYPE 
5

Nota: Solo probé esto en Oracle 11g.

Tuve una necesidad similar y me resultó más fácil simplemente declarar una función (sin el paquete) para devolver el valor deseado. Para ponerlos en ddl para la importación, recuerde separar cada declaración de función con el carácter /. Por ejemplo:

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

Esto permite hacer referencia a la función como si fuera un valor constante (por ejemplo, usted ni siquiera necesita los paréntesis).

Por ejemplo (observe los métodos to_char para mostrar que la precisión se ha conservado): SQL> seleccione undefined_int desde dual;

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

SQL> seleccionar undefined_string desde dual;

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

SQL> seleccionar undefined_double from dual;

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

SQL> select to_char (undefined_double, '9.999999999999999EEEE') de la doble;

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

SQL> select to_char (undefined_double, '9.99999999999999999EEEE') de la doble;

TO_CHAR(UNDEFINED_DOUBLE, 
------------------------- 
1.79769313486231550E+308 
6

Hay una manera más genérica que funciona bien para mí. Crea una función con el nombre de la constante de entrada (es decir, schema.package.constantname) y le devuelve el valor constante. Se hace uso de la ejecución inmediata de un bloque PL/SQL al enlazar la variable res (ver ejemplo).

función se ve así:

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

A continuación, puede utilizar la constante de cualquier paquete en cualquier SQL, es decir, como

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

como no se necesita sólo el 1 función y que toman la ventaja usar paquetes existentes .constantes.

+1

Gracias a la cláusula 'deterministic', esta es una solución bastante agradable. – nop77svk

+5

Buena idea, el único inconveniente es que los errores (por ejemplo, debido a errores tipográficos) no aparecerán hasta el tiempo de ejecución: su consulta se compilará sin error aunque se refiera a una constante inexistente. –

Cuestiones relacionadas