为什么Oracle的DECODE给我的价值与NVL不同?
这个查询:
select nvl(0.75,0) from dual
给我0.75
(数字),但这个查询:
select decode(1,0,null,0.75) from dual
给我'.75'
(字符串)。
为什么?
我试图通过将第二个查询更改为:
select decode(1,0,null,to_char(0.75,'0.99')) from dual
但在我的实际代码中,0.75将是一个字段(NUMBER),可能有不同的小数位数,我不想添加/删除该值的任何内容。
有关如何修复缺失零问题但仍支持所有可能的小数长度的任何想法?
这是因为你的decode语句的第3个参数是NULL; 根据文件 1 (我的重点)。
在比较之前, Oracle会自动将expr和每个搜索值转换为第一个搜索值的数据类型 ….如果第一个结果的数据类型为CHAR,或者第一个结果为null,则Oracle将返回值转换为数据类型VARCHAR2 。
在您的情况下,第一个结果是NULL,Oracle将其视为VARCHAR2。 您的返回值被隐式转换为VARCHAR2。 如果您将DECODE()
更改为以下内容,则会得到一个数字:
select decode(1, 0, 0, 0.75)
你可以使用NULLIF()
函数实现你的NULL:
select nullif(decode(1, 0, 0, 0.75), 0) ...
最好使用CASE语句,该语句强制所有返回的数据类型都相同:
select case 1 when 0 then null else 0.75 end ...
我也被抓住了。
您可以使用
select decode(1,0,to_number(null),0.75) from dual
在第一种情况下, nvl()
返回一个数值。 如何显示这取决于您用于运行查询的程序。 TOAD显示就像你说的那样,0.75。
在第二个示例中, decode()
返回varchar2
。 当Oracle将数字转换为字符串而没有任何格式时,这就是你得到的,即“.75”。
来自于decode()
上的Oracle文档:
如果第一个结果具有数据类型CHAR或第一个结果为null,则Oracle将返回值转换为数据类型VARCHAR2。
您可以使用数字格式和rtrim()
来实现您的目的,例如:
select rtrim(to_char(.75, '9990.99999999999999'),'0') from dual;
结果:
0.75
select to_number(decode(1,0,null,0.75)) from dual