Oracle NVL无效号码

时间:2016-09-12 17:44:51

标签: sql oracle

我有两个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_COMPNLS_SORTNLS_LANGUAGE的值在两个数据库之间是相同的,因此它们不应该导致2个参数的数字优先级不同。这两个数据库之间可能有什么不同,导致一个返回'ok'而一个返回错误?

3 个答案:

答案 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。