在ORACLE数据库中,NUMBER(P,S)是最常见的数字类型,可以存放数据范围为10^-130~10^126(不包含此值),需要1~22字节(BYTE)不等的存储空间。P 是Precison的英文缩写,即精度缩写,表示有效数字的位数,最多不能超过38个有效数字。S是Scale的英文缩写,表示从小数点到最低有效数字的位数,它为负数时,表示从最大有效数字到小数点的位数。有时候,我们在创建表的时候,NUMBER往往没有指定P,S的值,那么默认情况下,NUMBER的P、S的值分别是多少呢?相信这个问题能问倒一大片DBA。 在之前,我遇到了一个问题,总结整理在“ORACLE NUMBER类型Scale为0引发的问题”这篇博客当中,当时武断的判断“如果不指定p和s,NUMBER类型,它的默认精度值为38, 默认的scale值为0”,因为当时参考了官方文档https://docs.oracle.com/cd/B28359_01/server.111/b28318/datatype.htm#CNCPT1832

当然文档没有错误,文档应该是指在定义字段数据类型为NUMBER时,指定了NUMBER类型的P值,但是没有指定S的值,那么Scale默认就是0,如下测试所示,当时应该是我自己没有完全理解文档意思,当然文档也有误导的嫌疑。

SQL> drop table test;

 

Table dropped.

 

SQL> create table test(id number(38));

 

Table created.

 

SQL> insert into test

  2  select 123 from dual union all

  3  select 123.123 from dual;

 

2 rows created.

 

SQL> commit;

 

Commit complete.

 

SQL> select * from test;

 

        ID

----------

       123

       123

 

SQL> 

当在指定字段类型为NUMBER时,如果P和S都不指定,那么P和S又是什么值呢?今天特意实验验证了一下,具体实验过程如下:

SQL> drop table test;

 

Table dropped.

 

SQL> create table test(id  number, id1 number(38,4));

 

Table created.

 

SQL> insert into test                                      

  2  select 12, 12 from dual union all

  3  select 12.123456789, 12.123456789 from dual;

 

2 rows created.

 

SQL> commit;

 

Commit complete.

 

SQL> col id  for 999999999999.999999999999999999999999999999999999;

SQL> col id1 for 99999999999.9999999999999999999999999999999999999;

SQL> select * from test;

 

                                                ID                                                ID1

-------------------------------------------------- --------------------------------------------------

           12.000000000000000000000000000000000000           12.0000000000000000000000000000000000000

           12.123456789000000000000000000000000000           12.1235000000000000000000000000000000000

 

SQL> 

如上所示,当我插入上面两条记录后,发现如果不指定p和s,NUMBER类型,此时的Scale至少是9,我们继续测试,插入下面数据

SQL> insert into test

  2  select 12.123456789123456789123456789123456,

  3         12.123456789123456789123456789123456

  4  from dual;

 

1 row created.

 

SQL> commit;

 

Commit complete.

 

SQL> select * from test;

 

                                                ID                                                ID1

-------------------------------------------------- --------------------------------------------------

           12.000000000000000000000000000000000000           12.0000000000000000000000000000000000000

           12.123456789000000000000000000000000000           12.1235000000000000000000000000000000000

           12.123456789123456789123456789123456000           12.1235000000000000000000000000000000000

如下所示,此时可以看到Scale的值33了,那么Scale的值是否可以继续变大呢?

SQL> insert into test

  2  select 12.123456789123456789123456789123456789123,

  3         12.123456789123456789123456789123456789123

  4  from dual;

 

1 row created.

 

SQL> commit;

 

Commit complete.

 

SQL> select * from test;

 

                                                ID                                                ID1

-------------------------------------------------- --------------------------------------------------

           12.000000000000000000000000000000000000           12.0000000000000000000000000000000000000

           12.123456789000000000000000000000000000           12.1235000000000000000000000000000000000

           12.123456789123456789123456789123456000           12.1235000000000000000000000000000000000

           12.123456789123456789123456789123456789           12.1235000000000000000000000000000000000

如下截图所示,插入的记录为12.123456789123456789123456789123456789123,但是显示的值为12.123456789123456789123456789123456789,总共为38位,由于格式化列的缘故,可能导致部分小数位没有显示,

我们继续测试,调整格式化列,我们发现值变为了12.12345678912345678912345678912345678912,总共40位了,Scale的值为38了。这个是为什么呢?不是数字精度为38,意味着最多是38位吗?

SQL> col id  for 999999999999.99999999999999999999999999999999999999999

SQL> col id1 for 99999999999.999999999999999999999999999999999999999999

SQL> select * from test;

 

                                                     ID                                                     ID1

------------------------------------------------------- -------------------------------------------------------

           12.00000000000000000000000000000000000000000           12.000000000000000000000000000000000000000000

           12.12345678900000000000000000000000000000000           12.123500000000000000000000000000000000000000

           12.12345678912345678912345678912345600000000           12.123500000000000000000000000000000000000000

           12.12345678912345678912345678912345678912000           12.123500000000000000000000000000000000000000

继续其它测试,我们发现Sacle的值会随着小数点前面数字的变化而变化,如下所示:

SQL> insert into test

  2  select 123456789.123456789123456789123456789123456,

  3         123456789.123456789123456789123456789123456

  4  from dual;

 

1 row created.

 

SQL> commit;

 

Commit complete

 

SQL> insert into test

  2  select 123456789123.123456789123456789123456789123456,

  3         123456789123.123456789123456789123456789123456

  4  from dual;

 

1 row created.

 

SQL> commit;

 

Commit complete.

SQL> select * from test;

 

                                                     ID                                                     ID1

------------------------------------------------------- -------------------------------------------------------

           12.00000000000000000000000000000000000000000           12.000000000000000000000000000000000000000000

           12.12345678900000000000000000000000000000000           12.123500000000000000000000000000000000000000

           12.12345678912345678912345678912345600000000           12.123500000000000000000000000000000000000000

           12.12345678912345678912345678912345678912000           12.123500000000000000000000000000000000000000

    123456789.12345678912345678912345678912300000000000    123456789.123500000000000000000000000000000000000000

 123456789123.12345678912345678912345678910000000000000 #######################################################

 

6 rows selected.

从上面测试可以看出,Scale的值是变化的,跟数据值有关系,目前看来,小数点前的数字位数和小数点后的数字位数相加为40(有时候又是39),为了测试是否这个规律,我特意用下面案例测试一下

SQL> create table test2(id number);

 

Table created.

 

SQL> insert into test2

  2  select 0.123456789123456789123456789123456789123456789 from dual;

 

1 row created.

 

SQL> commit;

 

Commit complete.

 

SQL> col id for 9999999999.9999999999999999999999999999999999999999999999;

SQL> select * from test2;

 

                                                        ID

----------------------------------------------------------

           .1234567891234567891234567891234567891235000000

 

SQL> insert into test2

  2  select 123456789.123456789123456789123456789123456789 from dual;

 

1 row created.

 

SQL> commit;

 

Commit complete.

 

SQL> select * from test2;

 

                                                        ID

----------------------------------------------------------

           .1234567891234567891234567891234567891235000000

  123456789.1234567891234567891234567891230000000000000000

 

SQL> insert into test2

  2  select 123456789123.123456789123456789123456789123456789 from dual;

 

1 row created.

 

SQL> commit;

 

Commit complete.

 

SQL> select * from test2;

 

                                                        ID

----------------------------------------------------------

           .1234567891234567891234567891234567891235000000

  123456789.1234567891234567891234567891230000000000000000

##########################################################

 

SQL>  col id for 9999999999999.9999999999999999999999999999999999999999999999;

SQL> select * from test2;

 

                                                           ID

-------------------------------------------------------------

              .1234567891234567891234567891234567891235000000

     123456789.1234567891234567891234567891230000000000000000

  123456789123.1234567891234567891234567891000000000000000000

 

SQL> insert into test2

  2  select 12345678912345.12345678912345678912345678912345 from dual;

 

1 row created.

 

SQL> commit;

 

Commit complete.

 

SQL> select * from test2;

 

                                                           ID

-------------------------------------------------------------

              .1234567891234567891234567891234567891235000000

     123456789.1234567891234567891234567891230000000000000000

  123456789123.1234567891234567891234567891000000000000000000

#############################################################

 

SQL> col id for 9999999999999999999.99999999999999999999999999999999999999999999;

SP2-0246: Illegal FORMAT string "9999999999999999999.99999999999999999999999999999999999999999999"

SQL> col id for 9999999999999999999.9999999999999999999999999999999999999999

SQL> select * from test2;

 

                                                           ID

-------------------------------------------------------------

                    .1234567891234567891234567891234567891235

           123456789.1234567891234567891234567891230000000000

        123456789123.1234567891234567891234567891000000000000

      12345678912345.1234567891234567891234567900000000000000

 

SQL> 

这个问题纠结了很久,不明白为什么是39或40,后面在Oracle Database SQL Reference 10g Release 2终于找到解释了,如下所示:

p is the precision, or the total number of significant decimal digits, where the most

significant digit is the left-most nonzero digit, and the least significant digit is the

right-most known digit. Oracle guarantees the portability of numbers with

precision of up to 20 base-100 digits, which is equivalent to 39 or 40 decimal digits

depending on the position of the decimal point.

p是精度,或是有效十进制数的总位数。最大的有效数字是最左边的非零数字,而最小有效位是最右边的数字。 Oracle保证数字的可移植性

精度高达20 base-100 digits,相当于39位或40位十进制数字,取决于小数点的位置。

ORACLE 中NUMBER类型默认的精度和Scale问题的更多相关文章

  1. 对于Oracle中Number类型的字段映射成Java中的具体类型的问题

    我在Oracle中给一个用户Id字段设置为Number类型,使用JDBC在完成ORM的时候,以为其可以自动转换为Integer,因为我的POJO类id使用的就是Integer.但事实是,我在测试的时候 ...

  2. ORACLE 中NUMBER 类型 低精度转换成高精度

    例如: 表User中有一个字段 salary  Number(10,3), 如果想把字段salary的类型提高精度到salary  Number(10,6),保留六位小数, 解决办法:1,ALTER ...

  3. oracle中number类型的数据使用as string 得到的值为null

    1,如果数据的运行时类型(和数据库字段类型相同)不是字符串类型,比如number/date等,将ds.Tables[0].Rows[i][j] 调用 as string 时,不管 这个字段是否有值,这 ...

  4. oracle中number类型最简单明了解释

    NUMBER (p,s) p和s范围: p 1-38 s -84-127 number(p,s),s大于0,表示有效位最大为p,小数位最多为s,小数点右边s位置开始四舍五入,若s>p,小数点右侧 ...

  5. oracle中日期类型 to_date 和to_timestamp什么区别啊?

    1.to_date() 和to_timestamp()区别 由于oracle中date类型只支持到秒,不支持到毫秒,所以to_date()不能取到毫秒.如果要取到毫秒,oracle 9i以上版本,可以 ...

  6. Oracle中Clob类型处理解析:ORA-01461:仅可以插入LONG列的LONG值赋值

    感谢原作者:破剑冰-Oracle中Clob类型处理解析 上一篇分析:ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值 最近为Clob字段在插入数据时发现当字符的字节数(一个半角字符一 ...

  7. Spark SQL读取Oracle的number类型的数据时精度丢失问题

    Spark SQL读取数据Oracle的数据时,发现number类型的字段在读取的时候精度丢失了,使用的spark版本是Spark2.1.0的版本,竟然最后经过排查和网上查资料发现是一个bug.在Sp ...

  8. .Net处理Oracle中Clob类型字段总结

    最近在做项目中用到Clob这个字段,Clob是存储无限长字符的Oracle字段,用的时候网上找资料找了好久,内容不是很多,大部分都不能用,当然也有可以用的,测试了不同版本,整理了一下,给大家在做项目的 ...

  9. ORACLE中date类型字段的处理

    (1)在英文版本的ORACLE中默认日期格式为'DD-MON-YY',例如'01-JAN-98' 在汉化的中文版本中ORACLE默认日期格式为'日-月-年',例如'21-8月-2003'或'21-8月 ...

随机推荐

  1. c#后台调用API

    前两周赶上项目第一个版本上线,着实忙了一把,毕竟只有两个人负责.如今已完结,总算喘了一口气,现在任务就是写API.测API,许久之前写过JS前台调用 项目API,也写过后台调用开放的手机号归属地查询, ...

  2. NOI2001 食物链

    食物链 题目描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B 吃 C,C 吃 A. 现有 N 个动物,以 1 - N 编号.每个动物都是 A,B,C 中的一种 ...

  3. js、jQuery实现2048小游戏

    2048小游戏 一.游戏简介:  2048是一款休闲益智类的数字叠加小游戏 二. 游戏玩法: 在4*4的16宫格中,您可以选择上.下.左.右四个方向进行操作,数字会按方向移动,相邻的两个数字相同就会合 ...

  4. 用fiddler2调试localhost

    1.用 http://localhost. (locahost紧跟一个点号): 2.用 http://127.0.0.1. (127.0.0.1紧跟一个点号): 3.用 http://machinen ...

  5. Swing EDT引起的客户端卡死

    最近调试程序时发现,点击某个界面时会出现卡死的情况,出现的频率还是比较频繁的. 再次出现卡死的情况后,利用jvisualvm查看线程的运行情况,dump操作之后发现线程间出现了死锁: Found on ...

  6. BZOJ 3731 3731: Gty的超级妹子树 [树上size分块 !]

    传送门 题意:一棵树,询问子树中权值大于k的节点个数,修改点权值,插入新点,断开边:强制在线 该死该死该死!!!!!! MD我想早睡觉你知不知道 该死该死沙比提 断开边只会影响一个块,重构这个块就行了 ...

  7. POJ 2154 Color [Polya 数论]

    和上题一样,只考虑旋转等价,只不过颜色和珠子$1e9$ 一样的式子 $\sum\limits_{i=1}^n m^{gcd(i,n)}$ 然后按$gcd$分类,枚举$n$的约数 如果这个也化不出来我莫 ...

  8. HDU 2141 Can you find it? [二分]

    Can you find it? Give you three sequences of numbers A, B, C, then we give you a number X. Now you n ...

  9. DNA序列组装(贪婪算法)

    生物信息学原理作业第四弹:DNA序列组装(贪婪算法) 原理:生物信息学(孙啸) 大致思想: 1. 找到权值最大的边: 2. 除去以最大权值边的起始顶点为起始顶点的边: 3. 除去以最大权值边为终点为终 ...

  10. Delegate &&Lambda

    匿名函数及委托的使用: public delegate void NoReturnNoParaOutClass();//delegate can be defined in class or out ...