我有两个Oracle 12c(12.1.0.2.0)数据库,其中一个数据库返回'ok'
以进行以下查询(使用SQL Developer 3.2.20.10),而另一个数据库返回ORA-01722: invalid number
:
select 'ok' from dual where 1 = nvl(1, 'X');
NVL
的Oracle文档说:
如果expr1是数字,则Oracle确定哪个参数具有最高的数字优先级,隐式地将另一个参数转换为该数据类型,并返回该数据类型。
NLS_COMP
,NLS_SORT
和NLS_LANGUAGE
的值在两个数据库之间是相同的,因此它们不应该导致2个参数的数字优先级不同。这两个数据库之间可能有什么不同,导致一个返回'ok'
而一个返回错误?
答案 0 :(得分:4)
cursor_sharing可能是关键因素。
谓词“1 = nvl(1,'X')”可以在解析时计算,如果它始终作为文字执行并优化为true或false。但是,如果cursor_sharing是强制的,则所有三个文字都可以替换其他值,并且在执行之前无法计算表达式。
我必须使用两个单独的本地表来测试它。
alter session set cursor_sharing=force;
create table me_dual as select * from dual;
select 'ok' from me_dual x where 1 = nvl(1, 'A');
select 'ok' from me_dual x where 1 = nvl(1, 'A')
ERROR at line 1:
ORA-01722: invalid number
*
alter session set cursor_sharing=exact;
create table alt_dual as select * from dual;
select 'ok' from alt_dual x where 1 = nvl(1, 'A');
'O
--
ok
答案 1 :(得分:1)
将NVL的列参数包装在“ to_char ”中解决了我的问题“ORA-01722:无效数字”错误:
select 'ok' from dual where 1 = nvl(to_char(1), 'X');
答案 2 :(得分:0)
这很可爱......这不是答案,但我不能以任何可读的清晰度在评论中发布。
这一切都在同一个实例(oracle 11)上运行......但我认为它显示了类似的问题。
SQL> select version from v$instance;
VERSION
-----------------
11.2.0.4.0
SQL> select * from dual where 1 = nvl(1,'X');
D
-
X
SQL> select nvl(1,'X') from dual;
select nvl(1,'X') from dual
*
ERROR at line 1:
ORA-01722: invalid number
SQL>
我记得以前见过这个,但不记得怎么解释它。 O.o
不确定为什么它似乎在WHERE和SELECT子句之间以不同的方式评估NVL。