Por favor considere el siguiente script:
create or replace function f(p_limit in integer) return integer as
begin
set_global_context ('limit', p_limit);
return p_limit;
end;
/
create view v as
select level as val from dual connect by level<=sys_context('global_context','limit');
select f(2), v.* from v;
/*
F(2) VAL
---------------------- ----------------------
2 1
2 2
*/
select f(4), v.* from v;
/*
F(4) VAL
---------------------- ----------------------
4 1
4 2
4 3
4 4
*/
¿Puedo confiar en que f(x)
se ejecute antes de que se lea el contexto dentro de la vista, como se ha ejecutado en este caso de prueba en 10.2?
SELECT stuff FROM dbo.FuncReturningTable(param)
o similar. Oracle probablemente tiene una funcionalidad equivalente. Sin embargo, si uso esto en grandes conjuntos de datos, tendré cuidado de monitorear el rendimiento: no estoy seguro de cuán brillante debería ser el planificador de consultas para hacer un plan eficiente a partir de dicha sintaxis.Respuestas:
No.
Si reescribe su vista con el filtro de contexto contra la cláusula where (en lugar de conectar por), obtendrá el valor establecido previamente para el contexto:
Como la cláusula where se evalúa antes de que se seleccionen las columnas, el valor pasado a la función no se establece hasta después de leer el contexto. La ubicación de la llamada sys_context en su consulta (seleccionar, dónde, agrupar por, etc.) afectará exactamente cuando se establece este valor.
fuente
En términos generales, no puede asumir con seguridad nada sobre el orden en que su DBMS hará las cosas al evaluar una sola instrucción SQL. Esta es la razón por la cual muchos DBMS no permitirán que las funciones utilizadas de esa manera tengan efectos secundarios (es decir, MSSQL no permitirá que las funciones establezcan el estado global / conexión, lo que está haciendo allí, o altere el contenido de la tabla). Una serie de declaraciones debe ejecutarse de una manera que tenga sentido de un paso al siguiente (es decir, se ejecutan en serie o de una manera que no se puede decir que no lo fueron), pero dentro de una sola declaración el planificador de consultas tiene un reinado libre siempre que no introduzca ambigüedad donde no existe (en su ejemplo, la ambigüedad ya existe porque la función tiene un efecto secundario que afecta la vista).
Si el planificador de consultas fuera lo suficientemente brillante como para detectar que la vista se ve afectada por los efectos secundarios de la función, ¿qué haría si se uniera a otra vista que llamara a esa función potencialmente con diferentes valores de entrada? Podría volverse muy peludo rápidamente: este tipo de cosas es la razón por la cual, en general, en cualquier contexto de programación, las funciones no deberían tener efectos más allá de su propia salida.
En este ejemplo específico, diría que es poco probable que se llame primero a f (x), ya que es "parte" de la declaración: es probable que el conjunto de resultados de la vista se recupere antes de cualquier función dentro del Se evalúa la lista de columnas a devolver. Por supuesto, esto variará según el DBMS utilizado: no soy un experto en Oracle y los resultados de su prueba muestran que la función parece llamarse primero en estos casos. Pero sería cauteloso de depender del orden de ejecución dentro de una sola instrucción SQL de todos modos, incluso si siempre funciona de la manera esperada en este momento, puede que no lo haga en futuras revisiones (a menos que esté documentado oficialmente en algún lugar que la ejecución siempre irá por aquí)
fuente
La documentación solo promete que "El optimizador primero evalúa las expresiones y condiciones que contienen constantes de la forma más completa posible". ( 10.2 , 11.2 ). No se garantiza que primero evaluará ninguna expresión en particular, o que no cambiará ese orden de vez en cuando (¿un nuevo parche en el mismo lanzamiento?).
fuente