ORACLE NUMBER类型Scale为0引发的问题

今天遇到了一个很有意思的NUMBER类型Scale引发的问题,我用一个简单的测试用例来展示一下这个案例。假如有个TEST的表,有个字段类型为NUMBER,我插入下面两条数据

CREATE TABLE TEST
(
     Category VARCHAR(12),
     QTY  NUMBER
)
 
INSERT INTO TEST
SELECT 'M', 12 FROM DUAL UNION ALL
SELECT 'C', 0.99999999999999999 FROM DUAL;
 
COMMIT;

此时直接查询表TEST,发现QTY字段值为1,

使用下面SQL语句统计时,SUM_QTY的值也是1

但是如果在游标里面获取该值的时候,你会发现字段QTY的值为原来的值.99999999999999999

DECLARE  CURSOR c_test
IS
   SELECT Category, SUM(QTY) AS SUM_QTY FROM TEST
   GROUP BY Category;
   
   c_row c_test%rowtype;
   
 begin 
       for c_row in c_test loop
           dbms_output.put_line('the result is ' || c_row.SUM_QTY);
       end loop;
 end;

the result is .99999999999999999

the result is 12

为什么会有这个奇怪的现象呢?
其实我们遇到这个案例时是按这个顺序反着的,最后发现是插入的值是0.999999999.
当然这个过程是非常纠结的。远非我们例子里面那样轻松简单。要解释这个问题,要从NUMBER类型说起,NUMBER (p, s) 声明一个定点数
p(precision)为精度,s(scale)表示小数点右边的数字个数,精度最大值为38,scale的取值范围为-84到127。
Number(p) 表示声明一个整数相当于Number(p, 0), 如果不指定p和s,NUMBER类型,它的默认精度值为38,
默认的scale值为0. 所以出现在SELECT语句中,一个值为.99999999999999999
的显示为1,但是在游标中,它获取的是这个字段的真实值,没有经过转化。所以出现了这个稀奇古怪的问题。虽然事后理顺过后觉得非常简单,但是当时不了解情
况下,觉得非常不可思议,非常纳闷!

 

另外附上定点数的精度(p)和刻度(s)遵循以下规则:
 当一个数的整数部分的长度 > p-s 时,Oracle就会报错
 当一个数的小数部分的长度 > s 时,Oracle就会舍入。
 当s(scale)为负数时,Oracle就对小数点左边的s个数字进行舍入。
 当s > p 时, p表示小数点后第s位向左最多可以有多少位数字,如果大于p则Oracle报错,小数点后s位向右的数字被舍入

时间: 2024-10-03 11:14:21

ORACLE NUMBER类型Scale为0引发的问题的相关文章

ORACLE NUMBER类型详解

1>.NUMBER类型细讲:Oracle number datatype 语法:NUMBER[(precision [, scale])]简称:precision --> p      scale     --> s NUMBER(p, s)范围: 1 <= p <=38, -84 <= s <= 127保存数据范围:-1.0e-130 <= number value < 1.0e+126   保存在机器内部的范围: 1 ~ 22 bytes 有效为:

ORACLE NUMBER类型内部实现

先来研究NUMBER类型的数字回推算法 类型 <[长度]>,符号/指数位 [数字1,数字2,数字3,......,数字20] 1.长度类型没什么号说的 2.符号位,这个需要说一下 The sign bit, which is the high order bit (128) 按照文档的说法这个判断方法是和128进行最高位按位与出来的,如果 这位小于128则是负数,我们使用127试试吧 128的二进制为1000 0000  127的二进制为0111 1111 最高位1&0=0 则代表他是

oracle中dump函数及oracle NUMBER类型内部存储机制

oracle中dump函数 转自:http://blog.vsharing.com/nimrod/A654847.html DUMP函数的输出格式类似: 类型 ,符号/指数位 [数字1,数字2,数字3,......,数字20] 各位的含义如下: 1.类型: Number型,Type=2 (类型代码可以从Oracle的文档上查到) 2.长度:指存储的字节数 3.符号/指数位 在存储上,Oracle对正数和负数分别进行存储转换: 正数:加1存储(为了避免Null)负数:被101减,如果总长度小于21

ORACLE 中NUMBER类型默认的精度和Scale问题

在ORACLE数据库中,NUMBER(P,S)是最常见的数字类型,可以存放数据范围为10^-130~10^126(不包含此值),需要1~22字节(BYTE)不等的存储空间.P 是Precison的英文缩写,即精度缩写,表示有效数字的位数,最多不能超过38个有效数字.S是Scale的英文缩写,表示从小数点到最低有效数字的位数,它为负数时,表示从最大有效数字到小数点的位数.有时候,我们在创建表的时候,NUMBER往往没有指定P,S的值,那么默认情况下,NUMBER的P.S的值分别是多少呢?相信这个问

[20150503]关于oracle的number类型.txt

[20150503]关于oracle的number类型.txt --节前的事情,别人建表使用number类型,本来想定义成number(10,2),结果少输入0,变成number(1,2). --在我的记忆里,好像前面的数值应该大于后面的精度的,没想到这样竟然可以通过,自己感到很奇怪! --测试下来,才知道自己oracle基本的东西都不是很清楚. 1.首先提到我以前写的一篇blog: [20140823]在sqlplus使用copy注意.txt http://blog.itpub.net/267

Oracle中的number类型

number类型用于定义固定长度的数字,可以使整数,也可以是实数.number(p,s)是完整的定义形式. p必须是整数,取值范围是1-38,用于指定数字的总的位数.s必须是整数,取值范围是-84~127,用于指定小数点之后的位数. NUMBER 赋值:1234.56 实际:1234.56 NUMBER(3) 赋值:-123 实际:-123 NUMBER(3) 赋值:1234 实际:错误(ORA-06502:PL/SQL:数字或值错误:数字精度太高) NUMBER(4,3) 赋值:1.23456

[20160828]number类型.txt

[20160828]number类型.txt --昨天看了一个链接http://www.cnblogs.com/kerrycode/p/4427352.html,感觉有点不对,上班测试看看. 1.环境: SCOTT@book> @ &r/ver1 PORT_STRING                    VERSION        BANNER ------------------------------ -------------- -------------------------

oracle复合类型-oracle 存储过程 返回复合数据类型(index by表) ibatis如何接受

问题描述 oracle 存储过程 返回复合数据类型(index by表) ibatis如何接受 最近有个问题一直困扰着,希望各位能给予帮助. 先贴代码: 1 2 3 jdbcType="Object" mode="IN" /> 4 5 jdbcType="ARRAY" mode="OUT" typeHandler="com.diy.object.entity.ObjectTypeHandler" /&

Oracle Lob类型存储浅析

  在Oracle中,为数据表字段column和PL/SQL语言,分别提供了多种数据类型,以应对实际开发中的多种类型.Lob类型是Oracle推出一种保存大对象的数据类型.当我们考虑将信息文件(十进制.二进制).图像甚至音频信息采用数据库作为保存载体时,就需要使用lob类型数据.   目前Oracle支持的Lob类型具体包括四个子类型(subtype),分别为CLOB.BLOB.NLOB和BFILE.其中,CLOB.BLOB和NLOB都是将数据保存在数据库内部,而BFILE类型保存的核心是文件指