前言
遇到一个比较奇葩的需求,数据表有两个字段类型都是number(18,6),a字段存储的是未经处理的数字,比如0.233350这样的;b字段存储的是由程序经过四舍五入后的数字,比如0.233000。实际上用户输入的数据得出的结果确实是0.233350。
因为业务的需要,当比对两个字段的值有差异时,系统会认为有异常。
程序是第三方公司写的,改不了代码,那就只能从数据库开始着手了。
根据小数的特点,有以下几个思路
思路一、判断小数部分有效长度
比如0.233000的小数部分有效长度是3;0.233300的小数部分有效长度是4。
特殊情况,当数字是一个整数时,比如 100.000000的小数部分有效长度是0。
那么我们来构造一下sql语句
分别以数字999.233000、999.233300以及999.000000来举例
select 999.233000 fnumber,
case when instr(to_char(999.233000),'.')=0 then 0
else
length(substr(to_char(999.233000),instr(to_char(999.233000),'.')+1,length(to_char(999.233000))-instr(to_char(999.233000),'.')))
end flength
from dual999.233000得到的结果是
![]()
999.233300得到的结果是
![]()
999.000000得到的结果是

这个结果是符合预期的。
这种思路的判断条件是数位是否超过3,超过3的表示有3位以上的数位。
思路二、不判断有效数位,利用字符串的特性判断最后三位是否等于000
注意:这个思路是有前提的,只适用于特定精度情况下。
如果直接把小数用to_char函数转成字符串,会自动把后面的0去掉;
那么如何判断呢?首先根据字段类型可以知道,精度是6位小数,那么只需要把小数转成整数即可使用to_char函数转字符串,而不会丢失精度。
同样以数字999.233000、999.233300以及999.000000来举例
select 999.233000 fnumber,to_char(999.233000*1000000) fmultinumber,substr(to_char(999.233000*1000000),-3,3) flast3char from dual
999.233000得到的结果是
![]()
999.233300得到的结果是
![]()
999.000000得到的结果是
![]()
同样地,结果也是符合预期的。
这种思路的判断条件是flast3char是否等于000。
需要注意的是这种思路中,相乘的那个基数是受字段的精度影响的,比如如果字段是number(18,3)的话,那么就要乘以1000。
思路三、将小数转换成整数,再除以1000,判断结果是否为小数
这是在思路二的基础上发展而来,思路二中字段乘以1000000后会变成一个整数,如果进一步再除以1000的话,判断结果是否为小数就能解决问题。
同样以数字999.233000、999.233300以及999.000000来举例
select 999.233000 fnumber,to_char(999.233000*1000000/1000) fmultinumber,
instr(to_char(999.233000*1000000/1000),'.') fpointindex
from dual999.233000得到的结果是

999.233300得到的结果是

999.000000得到的结果是

同样结果也是符合预期的。
这种思路只需要判断fpointindex是否大于0就可以。
与思路二一样,这种思路中,相乘的那个基数也是受字段的精度影响的,比如如果字段是number(18,3)的话,那么就要乘以1000。
而除法的基数,则是根据小数后要保留多少个0来决定,比如要保留2个0,则除以100
总结
到此这篇关于oracle判断小数部分的有效长度两种思路总结的文章就介绍到这了,更多相关oracle判断小数部分有效长度内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论