2010-01-07 3 views
7

Кто-нибудь знает, почему функция Oracle NVLNVL2) всегда оценивает второй параметр, даже если первый параметр не равен NULL?Почему NVL всегда оценивает второй параметр

Простой тест:

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.

ответ

8

Это всегда было так, поэтому Oracle должен поддерживать его таким образом, чтобы оставаться обратно совместимым.

Вместо этого используйте COALESCE, чтобы получить короткое замыкание.

+1

Предостережение: оно не замыкается в 9i. –

3

В общем, это имело бы смысл, что второй параметр вычисляется перед вызовом функции, потому что в целом, что является, как функции называются: все аргументы функции оцениваются и оцененные значения отправляются в функцию.

Однако, в случае очень распространенной системной функции, такой как NVL, я бы подумал, что PL/SQL может оптимизировать, рассматривая вызов функции как особый случай. Но, возможно, это сложнее, чем кажется (мне), так как я уверен, что эта оптимизация возникла бы у разработчиков Oracle.

5

Это сообщение, в котором Tom Kyte подтверждает, что decode и case короткое замыкание, но не nvl, но он не дает обоснования или документации по причине. Просто заявляет, что это будет:

http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:926029357278#14932880517348

Так что в вашем случае вы должны использовать decode или case вместо nvl если дорогой функция будет вызываться в запросе.