Oracle Number型数值存储与转换的实现详解

Oracle在数据库内部通过相应的算法转换来进行数据存储,本文简单介绍Oracle的Number型数值存储及转换.这个内容是为了回答留言板上的2119号问题.
我们可以通过DUMP函数来转换数字的存储形式,一个简单的输出类似如下格式:


代码如下:

SQL> select dump(1) from dual;DUMP(1)
            ------------------
            Typ=2 Len=2: 193,2

DUMP函数的输出格式类似:
类型 <[长度]>,符号/指数位 [数字1,数字2,数字3,......,数字20]
各位的含义如下:
1.类型: Number型,Type=2 (类型代码可以从Oracle的文档上查到)
2.长度:指存储的字节数
3.符号/指数位
在存储上,Oracle对正数和负数分别进行存储转换:
正数:加1存储(为了避免Null)
负数:被101减,如果总长度小于21个字节,最后加一个102(是为了排序的需要)
指数位换算:
正数:指数=符号/指数位 - 193 (最高位为1是代表正数)
负数:指数=62 - 第一字节
4.从<数字1>开始是有效的数据位
从<数字1>开始是最高有效位,所存储的数值计算方法为:
将下面计算的结果加起来:
每个<数字位>乘以100^(指数-N) (N是有效位数的顺序位,第一个有效位的N=0)
5. 举例说明


代码如下:

SQL> select dump(123456.789) from dual;DUMP(123456.789)
            -------------------------------
            Typ=2 Len=6: 195,13,35,57,79,91

<指数>:   195 - 193 = 2
<数字1>    13 - 1    = 12 *100^(2-0) 120000
<数字2>    35 - 1    = 34 *100^(2-1) 3400
<数字3>    57 - 1    = 56 *100^(2-2) 56
<数字4>    79 - 1    = 78 *100^(2-3) .78
<数字5>    91 - 1    = 90 *100^(2-4) .009
                            123456.789


代码如下:

SQL> select dump(-123456.789) from dual;DUMP(-123456.789)
            ----------------------------------
            Typ=2 Len=7: 60,89,67,45,23,11,102

<指数>     62 - 60 = 2(最高位是0,代表为负数)
<数字1> 101 - 89 = 12 *100^(2-0) 120000
<数字2> 101 - 67 = 34 *100^(2-1) 3400
<数字3> 101 - 45 = 56 *100^(2-2) 56
<数字4> 101 - 23 = 78 *100^(2-3) .78
<数字5> 101 - 11 = 90 *100^(2-4) .009
                              123456.789(-)
现在再考虑一下为什么在最后加102是为了排序的需要,-123456.789在数据库中实际存储为
60,89,67,45,23,11
而-123456.78901在数据库中实际存储为
60,89,67,45,23,11,91
可见,如果不在最后加上102,在排序时会出现-123456.789<-123456.78901的情况。
对于2119号提问,第一个问题是:
1.请问为什么193,2各代表什么意思?
从上面就可以看到答案了.
2.还有NUMBER数字类型为什么有2个字节的长度呢?
对于这个问题,我想我们应该知道,所有数据类型最终在计算机里都以二进制存储,实际上所谓的数据类型都是我们定义的.所以存储只由算法决定.
所以这个问题是不成立的.比如:


代码如下:

SQL> select dump(110) from dual;DUMP(110)
            ---------------------
            Typ=2 Len=3: 194,2,11SQL> select dump(1100) from dual;DUMP(1100)
            -------------------
            Typ=2 Len=2: 194,12

我们会看到,虽然1100>110,但是存储上1100却只占2字节,而110却占了3个字节.

(0)

相关推荐

  • oracle to_char函数将number转成string

    很多数据转换处理操作时,会遇到将0.007007040000转换成0.70%的需求,我们使用Oracle 的SQL 函数 to_char可以实现这种转换. 这个函数用来将DATE或NUMBER数据类型转换成可显示的字符串,格式是to_char(number_type, format_mask). 格式'999.99',9表示对应的某一个指定位数的值,如果是值是0则忽略不显示,如果指定位数没有值,则以空格表示. 格式'0990.990',0表示对应的某一个指定位数的值,如果是值是0则显示为0,如果

  • Oracle 分析函数RANK(),ROW_NUMBER(),LAG()等的使用方法

    ROW_NUMBER() OVER (PARTITION BY COL1 ORDER BY COL2) 表示根据COL1分组,在分组内部根据 COL2排序 而这个值就表示每组内部排序后的顺序编号(组内连续的唯一的) RANK() 类似,不过RANK 排序的时候跟派名次一样,可以并列2个第一名之后 是第3名 LAG 表示 分组排序后 ,组内后面一条记录减前面一条记录的差,第一条可返回 NULL BTW: EXPERT ONE ON ONE 上讲的最详细,还有很多相关特性,文档看起来比较费劲 row

  • Oracle数字类型number自增的实现代码

    废话不多说了,直接给大家贴代码了,具体代码如下所示: 创建序列 create sequence seq_student start with 6 increment by 1 maxvalue 500 nominvalue nocycle nocache; 创建触发器 create or replace trigger trigger_student before insert on student for each row declare BEGIN select seq_student.ne

  • oracle中rownum和row_number()

    row_number()over(partition by col1 order by col2)表示根据col1分组,在分组内部根据col2排序,而此函数计算的值就表示每组内部排序后的顺序编号(组内连续的唯一的). 与rownum的区别在于:使用rownum进行排序的时候是先对结果集加入伪劣rownum然后再进行排序,而row_number()在包含排序从句后是先排序再计算行号码. 一.oracle中rownum 用于从查询返回的行的编号,返回的第一行分配的是1,第二行是2,依此类推,这个伪字

  • Oracle Number型的深入理解

    NUMBER数据类型NUMBER ( precision, scale)a)  precision表示数字中的有效位;如果没有指定precision的话,Oracle将使用38作为精度.b)  如果scale大于零,表示数字精确到小数点右边的位数:scale默认设置为0:如果scale小于零,Oracle将把该数字取舍到小数点左边的指定位数.c)  Precision的取值范围为[1---38]:Scale的取值范围为[-84---127].d)  NUMBER整数部分允许的长度为(precis

  • Oracle row_number() over()解析函数高效实现分页

    复制代码 代码如下: create table T_NEWS ( ID NUMBER, N_TYPE VARCHAR2(20), N_TITLE VARCHAR2(30), N_COUNT NUMBER ) prompt Disabling triggers for T_NEWS... alter table T_NEWS disable all triggers; prompt Loading T_NEWS... insert into T_NEWS (ID, N_TYPE, N_TITLE,

  • Oracle Number型数值存储与转换的实现详解

    Oracle在数据库内部通过相应的算法转换来进行数据存储,本文简单介绍Oracle的Number型数值存储及转换.这个内容是为了回答留言板上的2119号问题.我们可以通过DUMP函数来转换数字的存储形式,一个简单的输出类似如下格式: 复制代码 代码如下: SQL> select dump(1) from dual;DUMP(1)            ------------------            Typ=2 Len=2: 193,2 DUMP函数的输出格式类似:类型 <[长度]&

  • oracle中函数 trunc(),round(),ceil(),floor的使用详解

    1.round函数(四舍五入) 描述 : 传回一个数值,该数值是按照指定的小数位元数进行四舍五入运算的结果 参数: number : 欲处理之数值 decimal_places : 四舍五入 , 小数取几位 ( 预设为 0 ) select round(123.456, 0) from dual: 返回123 select round(123.456, 1) from dual; 返回123.5 select round(-123.456, 2) from dual; 返回-123.46 2.c

  • Java 存储模型和共享对象详解

    Java 存储模型和共享对象详解 很多程序员对一个共享变量初始化要注意可见性和安全发布(安全地构建一个对象,并其他线程能正确访问)等问题不是很理解,认为Java是一个屏蔽内存细节的平台,连对象回收都不需要关心,因此谈到可见性和安全发布大多不知所云.其实关键在于对Java存储模型,可见性和安全发布的问题是起源于Java的存储结构. Java存储模型原理 有很多书和文章都讲解过Java存储模型,其中一个图很清晰地说明了其存储结构: 由上图可知, jvm系统中存在一个主内存(Main Memory或J

  • java编程无向图结构的存储及DFS操作代码详解

    图的概念 图是算法中是树的拓展,树是从上向下的数据结构,结点都有一个父结点(根结点除外),从上向下排列.而图没有了父子结点的概念,图中的结点都是平等关系,结果更加复杂. 无向图                                                       有向图 图G=(V,E),其中V代表顶点Vertex,E代表边edge,一条边就是一个定点对(u,v),其中(u,v)∈V. 这两天遇到一个关于图的算法,在网上找了很久没有找到java版的关于数据结构中图的存储及其

  • JS的时间格式化和时间戳转换函数示例详解

    JS的时间格式化和时间戳转换函数 //格式化时间 function dateFormat(fmt,date){ var o = { "M+" : date.getMonth()+1, //月份 "d+" : date.getDate(), //日 "h+" : date.getHours(), //小时 "m+" : date.getMinutes(), //分 "s+" : date.getSeconds

  • Oracle 生成未来三天的整点时间(步骤详解)

    需求:X坐标轴时间都为整点时间,展示未来三天内的预测(x轴展示未来三天的整点时间),每3个小时一个刻度,横坐标共计24个刻度 步骤一:取当前时间 SELECT SYSDATE FROM DUAL 步骤二:取24个点 SELECT TO_NUMBER(ROWNUM - 1) AS RN,sysdate FROM DUAL CONNECT BY ROWNUM<25 步骤四:Oracle时间加减 SELECT SYSDATE + 1/24 FROM DUAL SYSDATE + 1表示时间加一天,1/

  • Oracle表中重复数据去重的方法实例详解

    Oracle表中重复数据去重的方法实例详解 我们在项目中肯定会遇到一种情况,就是表中没有主键 有重复数据 或者有主键 但是部分字段有重复数据 而我们需要过滤掉重复数据 下面是一种解决方法 delete from mytest ms where rowid in (select aa.rid from (select rowid as rid, row_number() over(partition by s.name order by s.id) as nu from mytest s) aa

  • Oracle删除表及查看表空间的实例详解

    Oracle常用的基本命令 --1.用户下表中注释模糊查询: 例如查询与优惠券关联的表 SELECT * FROM user_tab_comments t WHERE t.comments LIKE '%优惠券%'; ![这里写图片描述](http://img.blog.csdn.net/20170321112728053?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMDQyNzkzNQ==/font/5a6L5L2T/fontsize/40

  • oracle中创建序列及序列补零实例详解

    oracle中创建序列及序列补零实例详解 我们经常会在在DB中创建序列: -- Create sequence create sequence COMMON_SEQ minvalue 1 maxvalue 999999999 start with 1 increment by 1 cache 20 cycle; 我们的序列的最小值是从1开始,但是我们想让这种顺序取出来的序列的位数都一样,按照最大数的位数来算,我们需要8位的序列,那么我们就需要在1的前面补上7个零,只需要用下面的方法即可完成 se

  • C++ 中字符串操作--宽窄字符转换的实例详解

    C++ 中字符串操作--宽窄字符转换的实例详解 MultiByteToWideChar int MultiByteToWideChar( _In_ UINT CodePage, _In_ DWORD dwFlags, _In_ LPCSTR lpMultiByteStr, _In_ int cbMultiByte, _Out_opt_ LPWSTR lpWideCharStr, _In_ int cchWideChar ); 参数描述: CodePage:常用CP_ACP.CP_UTF8 dwF

随机推荐