oracle数值类型漫谈
发表于:2024-11-22 作者:千家信息网编辑
千家信息网最后更新 2024年11月22日,这片博客本来想的是只写pls_integer与number之间的性能比较,但是提笔之后我又想写更多我的思考过程,于是索性写一篇关于oracle数值类型的文章。干货太多,未免看得乏味,本篇我尝试用一种聊
千家信息网最后更新 2024年11月22日oracle数值类型漫谈这片博客本来想的是只写pls_integer与number之间的性能比较,但是提笔之后我又想写更多我的思考过程,于是索性写一篇关于oracle数值类型的文章。干货太多,未免看得乏味,本篇我尝试用一种聊天谈话的方式行文,希望同行者可以在一种轻松的氛围中和我一起来探讨oracle的诸多数值类型,好吧,那我就先抛砖引玉了。
1、number
我最先接触的数值类型就是老大哥number,它定义为number(p,s),p是精度,最大38位,s是刻度范围,可在-84~127间取值。举个栗子(例子):number(4,2),指的就是小数点整数+小数部分一共有4位,不包含小数点位,也就是说整数部分最多两位,如果小数部分多于2位,会做四舍五入处理(对于sqlserver和mysql也会做四舍五入处理),如果小数部分不足2位的话,则会补0(对于sqlserver也会补0,但是mysql不会),如果不写p,s,那么就默认为38。number类型是oracle最常用的数字类型了,在很长一段时间之内,我以为数值类型就只有number,因为number类型足以处理几乎全部的数字类型了。但是之后在oracle道路上继续行走的过程中,我又认识了其他衍生的数值类型。
2、integer
其实最开始看到这个数值类型的时候,同很多人一样,我也认为它是number类型的子类型,最大38位,对于小数做自动四舍五入处理,但是后来我发现不完全是这样的。作为number的子类型不假,一般情况下,integer是作为存储整数值存在的,在需要存储整数值的时候我们会想到这个数值类型,但是它的最大位可不是38位,在插入的测试数值看到,它已经远远超过38位了,如图:
可以看到,对于integer只能存储38位的言论可谓是直接推翻。接下来我们来看坊间盛传的,"integer只能存储整数,对于小数会做四舍五入处理",来看一个例子:
create or replace procedure integer_test(a integer)
as
b integer := a;
begin
dbms_output.put_line(b);
end;
输出结果如图:
看到这个结果的时候,相信很多同学都已经凉了,简直是颠覆了以往的认识啊,的确,从这个例子可以看出,integer是number的子类型,但是它不会强制进行四舍五入处理,同时它最大位数大于38位。
3、int,numeric,decimal
这三种数值类型是oracle为了兼容其他数据库而存在的,同样都是number的子类型。在进行类型声明的时候,如果直接声明为int,numeric,decimal,它会被直接存为integer,处理方式同integer一模一样;numeric和decimal如果带有精度和刻度范围,那么会被存为number(p,s),处理方式同number(p,s),int类型只能被声明为int,不能带精度和刻度范围,所以只能当作integer来处理。
4、float
float也是number的子类型,float(n),n指的是精度,是二进制精度,这里可不是十进制精度哦,计算公式为:binary precision=ceil(b*0.30103),float没有刻度范围.n的范围为1~126。那么怎么计算存入数据库中的数值呢,比如:float(2),那么它的精度是ceil(2*0.30103)=1,如果存入13.5,那么应该是1.35*10^1,精度为1,1.35四舍五入变为1,所以就是1*10^1=10存入的结果就是10;如果是19.5,那么应该是1.95*10^1,精度为1,1.95四舍五入为2,就是2*10^1,结果存入20。如果没有精度,那么映射为number类型,直接存入此值。oracle没有直接为double类型的数值类型。
5、binary_integer和pls_integer
这个数字类型只能用于PL/SQL,他们相比number来说更具优势,首先是占有较少的存储空间,其次他们是直接通过硬件来计算的,也就是直接通过CPU进行计算,而不用经过转换,number类型在计算的时候,还要先被转换为二进制,所以在计算速度上,binary_integer和pls_integer比number性能好很多,建议在PL/SQL中使用这两种数据类型来代替number,你将会得到很大的惊喜。
5、binary_float和binary_double
这两种数值类型10g之后才出现,binary_float可以存储一个单精度的32位浮点数,binary_double可以存储一个双精度的64位浮点数,binary_float和binary_double占有更少的存储空间,同样的,binary_float和binary_double也是直接通过硬件计算的,所以它的计算效率更高,而且它们比起number来说可以存储更大或者更小的数值,但是这两种数值类型也会存在精度不准的情况。
6、写到浮点型,我需要说一说浮点型存数不精确的原因:
首先,我们要知道浮点型在计算机是怎么存储的,比如:要存入13.75,首先将整数部分转为二进制,13转为二进制是1101,接下来将小数部分转为二进制,小数部分是0.75,将小数部分乘以2,取结果的整数部分为二进制的一位,然后继续取结果的小数部分乘以2重复,一直到小数部分全部为0结束,在这个过程中,是会出现循环乘不尽的情况,但是因为浮点数的小数位是确定的(float是23位,double是52位),所以到了指定的小数位就会停下来,这就是浮点数存数不精确的原因,可以看到如果可以在小数位范围之内乘尽的话,那么结果就存储的准确了。来看看小数部分(0.75)转为二进制的过程:
0.75*2=1.5 取1
0.5*2=1 取1
乘到这里,即0.5*2=1,1已经没有小数部分了,所以到这里也就停止了,最后的结果是0.11,与上面整数部分合起来,那么13.75转换为二进制为1101.11,即1.10111*2^3,1.10111是小数部分,2为底,6为指数部分,这个1.10111*2^3就是转换好的二进制浮点数,接着就是将这个二进制浮点数存入计算机了。
将其存入计算机内,将会使用浮点表示法,分为三大部分:
第一部分:符号位,占用1位,用来区分正负数,0为正数,1为负数;对于1.10111*2^3,它是正数,所以符号位是0
第二部分:指数位,float占用8位,double占用11位,用来表示指数;对于1.10111*2^3,指数位是3
第三部分:小数位,float占用23位,double占用52位,用来表示小数,不足位数补0;对于1.10111*2^3,小数位是10111
所以对于float,符号位+指数位+小数位=1+8+23=32位,对于double,符号位+指数位+小数位=64位,同时可以看到,指数位决定了大小范围,小数位决定了精度。因为指数位有可能是正数,也有可能是负数,负数算起来比正数麻烦,所以为了减少计算的麻烦,在存储指数的时候,需要将它存储位无符号的整数,所以在指数位上会加一个偏移量,float的偏移量是127,double的偏移量是1023,如果需要转换为十进制的话,到时候指数减去相应的值就可以了。那么对于13.75(float),本来它的二进制指数值是3,现在就成了3+127=130,转换为二进制是10000010,最终:13.75(float)被存储为:符号位 指数位 小数位(不足位补0)=0 10000010 10111 00000 00000 00000 000
7、万丈高楼平地起,有时候我们太过追求一些高级语法,或者高大尚的东西,反而在基础的东西上掌握不牢,实际上,数据库的基础数据类型往往没有表面上看的那么简单,其实任何语言都是一样,只有掌握好基础知识,做一个基础精通者,那么,在我们进阶的道路上就会水到渠成。写到最后,才发现整体下来,整篇文章也没有那么轻松,严肃的东西写惯了,一下子不太适应写轻松的东西,没事,能抛砖引玉就好。
1、number
我最先接触的数值类型就是老大哥number,它定义为number(p,s),p是精度,最大38位,s是刻度范围,可在-84~127间取值。举个栗子(例子):number(4,2),指的就是小数点整数+小数部分一共有4位,不包含小数点位,也就是说整数部分最多两位,如果小数部分多于2位,会做四舍五入处理(对于sqlserver和mysql也会做四舍五入处理),如果小数部分不足2位的话,则会补0(对于sqlserver也会补0,但是mysql不会),如果不写p,s,那么就默认为38。number类型是oracle最常用的数字类型了,在很长一段时间之内,我以为数值类型就只有number,因为number类型足以处理几乎全部的数字类型了。但是之后在oracle道路上继续行走的过程中,我又认识了其他衍生的数值类型。
2、integer
其实最开始看到这个数值类型的时候,同很多人一样,我也认为它是number类型的子类型,最大38位,对于小数做自动四舍五入处理,但是后来我发现不完全是这样的。作为number的子类型不假,一般情况下,integer是作为存储整数值存在的,在需要存储整数值的时候我们会想到这个数值类型,但是它的最大位可不是38位,在插入的测试数值看到,它已经远远超过38位了,如图:
可以看到,对于integer只能存储38位的言论可谓是直接推翻。接下来我们来看坊间盛传的,"integer只能存储整数,对于小数会做四舍五入处理",来看一个例子:
create or replace procedure integer_test(a integer)
as
b integer := a;
begin
dbms_output.put_line(b);
end;
输出结果如图:
看到这个结果的时候,相信很多同学都已经凉了,简直是颠覆了以往的认识啊,的确,从这个例子可以看出,integer是number的子类型,但是它不会强制进行四舍五入处理,同时它最大位数大于38位。
3、int,numeric,decimal
这三种数值类型是oracle为了兼容其他数据库而存在的,同样都是number的子类型。在进行类型声明的时候,如果直接声明为int,numeric,decimal,它会被直接存为integer,处理方式同integer一模一样;numeric和decimal如果带有精度和刻度范围,那么会被存为number(p,s),处理方式同number(p,s),int类型只能被声明为int,不能带精度和刻度范围,所以只能当作integer来处理。
4、float
float也是number的子类型,float(n),n指的是精度,是二进制精度,这里可不是十进制精度哦,计算公式为:binary precision=ceil(b*0.30103),float没有刻度范围.n的范围为1~126。那么怎么计算存入数据库中的数值呢,比如:float(2),那么它的精度是ceil(2*0.30103)=1,如果存入13.5,那么应该是1.35*10^1,精度为1,1.35四舍五入变为1,所以就是1*10^1=10存入的结果就是10;如果是19.5,那么应该是1.95*10^1,精度为1,1.95四舍五入为2,就是2*10^1,结果存入20。如果没有精度,那么映射为number类型,直接存入此值。oracle没有直接为double类型的数值类型。
5、binary_integer和pls_integer
这个数字类型只能用于PL/SQL,他们相比number来说更具优势,首先是占有较少的存储空间,其次他们是直接通过硬件来计算的,也就是直接通过CPU进行计算,而不用经过转换,number类型在计算的时候,还要先被转换为二进制,所以在计算速度上,binary_integer和pls_integer比number性能好很多,建议在PL/SQL中使用这两种数据类型来代替number,你将会得到很大的惊喜。
5、binary_float和binary_double
这两种数值类型10g之后才出现,binary_float可以存储一个单精度的32位浮点数,binary_double可以存储一个双精度的64位浮点数,binary_float和binary_double占有更少的存储空间,同样的,binary_float和binary_double也是直接通过硬件计算的,所以它的计算效率更高,而且它们比起number来说可以存储更大或者更小的数值,但是这两种数值类型也会存在精度不准的情况。
6、写到浮点型,我需要说一说浮点型存数不精确的原因:
首先,我们要知道浮点型在计算机是怎么存储的,比如:要存入13.75,首先将整数部分转为二进制,13转为二进制是1101,接下来将小数部分转为二进制,小数部分是0.75,将小数部分乘以2,取结果的整数部分为二进制的一位,然后继续取结果的小数部分乘以2重复,一直到小数部分全部为0结束,在这个过程中,是会出现循环乘不尽的情况,但是因为浮点数的小数位是确定的(float是23位,double是52位),所以到了指定的小数位就会停下来,这就是浮点数存数不精确的原因,可以看到如果可以在小数位范围之内乘尽的话,那么结果就存储的准确了。来看看小数部分(0.75)转为二进制的过程:
0.75*2=1.5 取1
0.5*2=1 取1
乘到这里,即0.5*2=1,1已经没有小数部分了,所以到这里也就停止了,最后的结果是0.11,与上面整数部分合起来,那么13.75转换为二进制为1101.11,即1.10111*2^3,1.10111是小数部分,2为底,6为指数部分,这个1.10111*2^3就是转换好的二进制浮点数,接着就是将这个二进制浮点数存入计算机了。
将其存入计算机内,将会使用浮点表示法,分为三大部分:
第一部分:符号位,占用1位,用来区分正负数,0为正数,1为负数;对于1.10111*2^3,它是正数,所以符号位是0
第二部分:指数位,float占用8位,double占用11位,用来表示指数;对于1.10111*2^3,指数位是3
第三部分:小数位,float占用23位,double占用52位,用来表示小数,不足位数补0;对于1.10111*2^3,小数位是10111
所以对于float,符号位+指数位+小数位=1+8+23=32位,对于double,符号位+指数位+小数位=64位,同时可以看到,指数位决定了大小范围,小数位决定了精度。因为指数位有可能是正数,也有可能是负数,负数算起来比正数麻烦,所以为了减少计算的麻烦,在存储指数的时候,需要将它存储位无符号的整数,所以在指数位上会加一个偏移量,float的偏移量是127,double的偏移量是1023,如果需要转换为十进制的话,到时候指数减去相应的值就可以了。那么对于13.75(float),本来它的二进制指数值是3,现在就成了3+127=130,转换为二进制是10000010,最终:13.75(float)被存储为:符号位 指数位 小数位(不足位补0)=0 10000010 10111 00000 00000 00000 000
7、万丈高楼平地起,有时候我们太过追求一些高级语法,或者高大尚的东西,反而在基础的东西上掌握不牢,实际上,数据库的基础数据类型往往没有表面上看的那么简单,其实任何语言都是一样,只有掌握好基础知识,做一个基础精通者,那么,在我们进阶的道路上就会水到渠成。写到最后,才发现整体下来,整篇文章也没有那么轻松,严肃的东西写惯了,一下子不太适应写轻松的东西,没事,能抛砖引玉就好。
类型
小数
部分
数值
存储
精度
二进制
小数位
处理
就是
数位
结果
四舍五入
整数
范围
四舍
时候
点数
符号
指数
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
单招面试选择网络技术的理由
股市软件开发流程
筑业软件怎样安装数据库文件
服务器带双子星计算系统
县级网络安全报告
新疆网络安全感想
网络技术主管述职报告
网络时代注意网络安全
2020街霸5服务器
网站放到服务器
swift编程用什么数据库
网络安全ppt策划书
文档软件开发便宜
数据库怎么用cmd打开
怎么进服务器raid管理界面
湖北特色软件开发市场报价
冗余服务器怎么仿真
gpu服务器规格型号
大庆公安局网络安全成立
北大版数据库
sr1000放映机服务器设置
近两年新网络技术
服务器 堡垒机
电脑应用程序用什么软件开发
计算机 网络安全顾问
封神榜服务器姜子牙
高科技法制文化教育基地软件开发
服务器风扇有电主板没电
杭州一站式网络技术服务价格
数据库技术提取数字