为什么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