Делает любой знает, почему Oracle NVL
(и NVL2
) функция всегда оценивает второй параметр, даже если первый параметр не NULL
?
Простой тест:
CREATE FUNCTION nvl_test RETURN NUMBER AS
BEGIN
dbms_output.put_line('Called');
RETURN 1;
END nvl_test;
SELECT NVL( 0, nvl_test ) FROM dual
возвраты 0
, но также и печать Called
.
nvl_test
был назван, даже при том, что результат проигнорирован, так как первый параметр не NULL
.
Так было всегда, поэтому Oracle должен сохранить его, чтобы сохранить обратную совместимость.
Используйте вместо него COALESCE
, чтобы получить поведение при коротком замыкании.
Вот сообщение, где Том Кайт подтверждает, что декодирует
и case
короткое замыкание, но не nvl
, но не дает обоснования или документации, объясняющей почему. Просто указывается:
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:926029357278#14932880517348
Так что в вашем случае вам следует использовать декодировать
или case
вместо nvl
, если в вашем запросе будет вызвана дорогостоящая функция.
В общем, имеет смысл, чтобы второй параметр вычислялся перед вызовом функции, потому что в общем так вызываются функции: все аргументы в функцию вычисляются, а вычисляемые значения посылаются в функцию.
Однако, в случае очень распространенной системной функции, такой как NVL, я бы подумал, что PL/SQL мог бы оптимизировать, рассматривая вызов функции как особый случай. Но, возможно, это сложнее, чем кажется (мне), так как я уверен, что такая оптимизация пришла бы в голову разработчикам Oracle
.Очевидно, что это не короткое замыкание, но я не могу найти никаких ссылок в документации Oracle.
Посмотрите на это обсуждение: http://forums.oracle.com/forums/thread.jspa?messageID=3478040