有谁知道,为什么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
。
答案 0 :(得分:8)
一直都是这样,因此Oracle必须保持这种方式以保持向后兼容。
使用COALESCE
来获取短路行为。
答案 1 :(得分: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
。
答案 2 :(得分:3)
通常,在调用函数之前计算第二个参数是有意义的,因为通常调用函数的方式是:计算函数的所有参数,并将计算值发送给函数。
然而,在像NVL这样非常常见的系统功能的情况下,我认为PL / SQL可以优化,将函数调用视为一种特殊情况。但也许这比听起来更困难(对我来说),因为我确信这种优化会发生在Oracle的开发者身上。
答案 3 :(得分:0)
它们显然不是短路的,但我在Oracle文档中找不到任何引用。
查看此讨论:http://forums.oracle.com/forums/thread.jspa?messageID=3478040