`
seawavenews
  • 浏览: 230123 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

Oracle基本数据类型存储格式浅析(三)——日期类型

阅读更多
这篇文章描述DATE类型的数据在Oracle中是以何种格式存放的。


下面通过一个例子进行说明。


SQL> create table test_date (date_col date);


表已创建。


SQL> insert into test_date values (to_date('2000-1-1 0:0:0', 'yyyy-mm-dd hh24:mi:ss'));


已创建 1 行。


SQL> insert into test_date values (to_date('1-1-1 0:0:0', 'yyyy-mm-dd hh24:mi:ss'));


已创建 1 行。


SQL> insert into test_date values (to_date('-1-1-1 0:0:0', 'syyyy-mm-dd hh24:mi:ss'));


已创建 1 行。


SQL> insert into test_date values (to_date('-101-1-1 0:0:0', 'syyyy-mm-dd hh24:mi:ss'));


已创建 1 行。


SQL> insert into test_date values (to_date('-4712-1-1 0:0:0', 'syyyy-mm-dd hh24:mi:ss'));


已创建 1 行。


SQL> insert into test_date values (to_date('9999-12-31 23:59:59', 'syyyy-mm-dd hh24:mi:ss'));


已创建 1 行。


SQL> insert into test_date values (sysdate);


已创建 1 行。


SQL> insert into test_date values (to_date('-4713-1-1 0:0:0', 'syyyy-mm-dd hh24:mi:ss'));
insert into test_date values (to_date('-4713-1-1 0:0:0', 'syyyy-mm-dd hh24:mi:ss'))
*
ERROR 位于第 1 行:
ORA-01841: (全)年度值必须介于 -4713 和 +9999 之间,且不为 0



SQL> insert into test_date values (to_date('0000-1-1 0:0:0', 'yyyy-mm-dd hh24:mi:ss'));
insert into test_date values (to_date('0000-1-1 0:0:0', 'yyyy-mm-dd hh24:mi:ss'))
*
ERROR 位于第 1 行:
ORA-01841: (全)年度值必须介于 -4713 和 +9999 之间,且不为 0



SQL> col dump_date format a80
SQL> select to_char(date_col, 'syyyy-mm-dd hh24:mi:ss'), dump(date_col) dump_date from test_date;


TO_CHAR(DATE_COL,'SY DUMP_DATE
-------------------- ---------------------------------------
2000-01-01 00:00:00 Typ=12 Len=7: 120,100,1,1,1,1,1
0001-01-01 00:00:00 Typ=12 Len=7: 100,101,1,1,1,1,1
-0001-01-01 00:00:00 Typ=12 Len=7: 100,99,1,1,1,1,1
-0101-01-01 00:00:00 Typ=12 Len=7: 99,99,1,1,1,1,1
-4712-01-01 00:00:00 Typ=12 Len=7: 53,88,1,1,1,1,1
9999-12-31 23:59:59 Typ=12 Len=7: 199,199,12,31,24,60,60
2004-12-15 13:56:19 Typ=12 Len=7: 120,104,12,15,14,57,20


已选择7行。





通过最后两条语句已经可以看出Oracle的DATE类型的取值范围是公元前4712年1月1日至公元9999年12月31日。而且根据日期的特定,要不然是公元1年,要不然是公元前1年,不会出现0年的情况。


日期类型长度是7,7个字节分别表示世纪、年、月、日、时、分和秒。


由于不会出现0的情况,月和日都是按照原值存储的,月的范围是1~12,日的范围是1~31。


由于时、分、秒都会出现0的情况,因此存储时采用原值加1的方式。0时保存为1,13时保存为14,23时保存为24。分和秒的情况与小时类似。小时的范围是0~23,在数据库中以1~24保存。分和秒的范围都是0~59,在数据库中以1~60保存。


年和世纪的情况相对比较复杂,可分为公元前和公元后两种情况。由于最小的世纪的值是-47(公元前4712年),最大值是99(公元9999年)。为了避 免负数的产生,oracle把世纪加100保存在数据库中。公元2000年,世纪保存为120,公元9999年,世纪保存为199,公元前101年,世纪 保存为99(100+(-1)),公元前4712年,世纪保存为53(100+(-47))。


注意,对于公元前1年,虽然已经是公元前了,但是表示世纪的前两位的值仍然是0,因此,这时的保存的世纪的值仍然是100。世纪的范围是-47~99,保存的值是53~199。


年的保存与世纪的保存方式类似,也把年的值加上100进行保存。对于公元2000年,年保持为100,公元1年保存为101,公元2004年保存为 104,公元9999年保存为199,公元前1年,保存为99(100+(-1)),公元前101年,保存为99(100+(-1)),公元前4712年 保存为88(100+(-12))。对于公元前的年,保存的值总是小于等于100,对于公元后的年,保存的值总是大于等于100。年的范围是0~99,保 存的值是1~199。


注意:一般的世纪,都包含了100年,而对于0世纪,由于包含公元前和公元后两部分且不包含0年,因此包含了198年。
 
这篇文章描述TIMESTAMP类型的数据在Oracle中是以何种格式存放的。


下面通过一个例子进行说明。







SQL> create table test_time (col_time timestamp);


表已创建。


SQL> insert into test_time values (to_timestamp('0001-1-1 0:0:0.0', 'syyyy-mm-dd hh24:mi:ss.ff'));


已创建 1 行。


SQL> insert into test_time values (to_timestamp('2000-1-1 0:0:0.0', 'syyyy-mm-dd hh24:mi:ss.ff'));


已创建 1 行。


SQL> insert into test_time values (to_timestamp('9999-12-31 23:59:59.999999', 'syyyy-mm-dd hh24:mi:ss.ff'));


已创建 1 行。


SQL> insert into test_time values (to_timestamp('-0001-1-1 0:0:0.0', 'syyyy-mm-dd hh24:mi:ss.ff'));


已创建 1 行。


SQL> insert into test_time values (to_timestamp('-0100-3-4 13:2:3.234015', 'syyyy-mm-dd hh24:mi:ss.ff'));


已创建 1 行。


SQL> insert into test_time values (systimestamp);


已创建 1 行。



SQL> insert into test_time values (to_timestamp('2000-1-1 0:0:0.123456789', 'syyyy-mm-dd hh24:mi:ss.ff9'));


已创建 1 行。


SQL> commit;


提交完成。


SQL> select to_char(col_time, 'syyyy-mm-dd hh24:mi:ss.ff9') time, dump(col_time) dump_time
2 from test_time;


TIME DUMP_TIME
------------------------------ ----------------------------------------------------
0001-01-01 00:00:00.000000000 Typ=180 Len=7: 100,101,1,1,1,1,1
2000-01-01 00:00:00.000000000 Typ=180 Len=7: 120,100,1,1,1,1,1
9999-12-31 23:59:59.999999000 Typ=180 Len=11: 199,199,12,31,24,60,60,59,154,198,24
-0001-01-01 00:00:00.000000000 Typ=180 Len=7: 100,99,1,1,1,1,1
-0100-03-04 13:02:03.234015000 Typ=180 Len=11: 99,100,3,4,14,3,4,13,242,201,24
2004-12-15 16:14:52.738000000 Typ=180 Len=11: 120,104,12,15,17,15,53,43,252,252,128
2000-01-01 00:00:00.123457000 Typ=180 Len=11: 120,100,1,1,1,1,1,7,91,205,232


已选择7行。


与DATE类型对比可以发现,对于TIMESTAMP类型,如果不包含微秒信息或者微秒值为0,那么存储结果和DATE完全相同。当微秒值为0时,Oracle为了节省空间,不会保存微秒信息。


如果毫秒值不为0,Oracle把微秒值当作一个9位数的数字来保存。


比如999999000,保存为59,154,198,24。234015000保存为13,242,201,24。


SQL> select to_char(999999000, 'xxxxxxxxxx') from dual;


TO_CHAR(999
-----------
3b9ac618


SQL> select to_number('3b', 'xxx') one, to_number('9a', 'xxx') two,
2 to_number('c6', 'xxx') three, to_number('18', 'xxx') four from dual;


ONE TWO THREE FOUR
---------- ---------- ---------- ----------
59 154 198 24


SQL> select to_char(234015000, 'xxxxxxxx') from dual;


TO_CHAR(2
---------
df2c918


SQL> select to_number('d', 'xxx') one, to_number('f2', 'xxx') two,
2 to_number('c9', 'xxx') three, to_number('18', 'xxx') four from dual;


ONE TWO THREE FOUR
---------- ---------- ---------- ----------
13 242 201 24





另外,注意一点,不指定精度的情况下,TIMESTAMP默认取6位。长度超过6位,会四舍五入到6位。如果希望保存9位的TIMESTAMP,必须明确指定精度。


SQL> alter table test_time modify (col_time timestamp(9));


表已更改。


SQL> insert into test_time values (to_timestamp('2000-1-1 0:0:0.123456789', 'syyyy-mm-dd hh24:mi:ss.ff9'));


已创建 1 行。


SQL> select to_char(col_time, 'syyyy-mm-dd hh24:mi:ss.ff9') time, dump(col_time) dump_time
2 from test_time;


TIME DUMP_TIME
------------------------------ ---------------------------------------------------
0001-01-01 00:00:00.000000000 Typ=180 Len=7: 100,101,1,1,1,1,1
2000-01-01 00:00:00.000000000 Typ=180 Len=7: 120,100,1,1,1,1,1
9999-12-31 23:59:59.999999000 Typ=180 Len=11: 199,199,12,31,24,60,60,59,154,198,24
-0001-01-01 00:00:00.000000000 Typ=180 Len=7: 100,99,1,1,1,1,1
-0100-03-04 13:02:03.234015000 Typ=180 Len=11: 99,100,3,4,14,3,4,13,242,201,24
2004-12-15 16:14:52.738000000 Typ=180 Len=11: 120,104,12,15,17,15,53,43,252,252,128
2000-01-01 00:00:00.123457000 Typ=180 Len=11: 120,100,1,1,1,1,1,7,91,205,232
2000-01-01 00:00:00.123456789 Typ=180 Len=11: 120,100,1,1,1,1,1,7,91,205,21


已选择8行。


出自:http://blog.itpub.net/post/468/10293
如果直接在SQL语句中对SYSDATE或由TO_DATE函数生成日期进行DUMP操作,会发现得到的结果与DUMP数据库中保存的日期的结果不一样。


SQL> truncate table test_date;


表已截掉。


SQL> insert into test_date values (to_date('2004-12-17 16:42:42', 'syyyy-mm-dd hh24:mi:ss'));


已创建 1 行。


SQL> col dump_date format a65
SQL> select to_char(date_col, 'syyyy-mm-dd hh24:mi:ss') dat, dump(date_col) dump_date from test_date;


DAT DUMP_DATE
-------------------- ---------------------------------------------------------
2004-12-17 16:42:42 Typ=12 Len=7: 120,104,12,17,17,43,43


SQL> select to_char(to_date('2004-12-17 16:42:42', 'syyyy-mm-dd hh24:mi:ss'), 'syyyy-mm-dd hh24:mi:ss') dat,
2 dump(to_date('2004-12-17 16:42:42', 'syyyy-mm-dd hh24:mi:ss')) dump_date from dual;


DAT DUMP_DATE
-------------------- ---------------------------------------------------------
2004-12-17 16:42:42 Typ=13 Len=8: 212,7,12,17,16,42,42,0


存储在数据库中的DATE类型是12,而直接在SQL中使用的DATE类型是13。而且二者的长度以及表示方式都不相同。这两种类型的不同指出主要体现在两点:一:时、分、秒的表示不同;二、世纪和年的表示不同。

SQL中使用DATE的时分秒没有采用加1存储方式,而且原值存储。

SQL中使用DATE没有采用世纪、年的方式保持,而是采用了按数值保存的方式。第一位表示低位,第二位表示高位。低位表示最大的值是255。如上面的例子中,212+7×256=2004。

SQL> select to_char(to_date('-2004-12-17 16:42:42', 'syyyy-mm-dd hh24:mi:ss'), 'syyyy-mm-dd hh24:mi:ss') dat,
2 dump(to_date('-2004-12-17 16:42:42', 'syyyy-mm-dd hh24:mi:ss')) dump_date from dual;


DAT DUMP_DATE
-------------------- ---------------------------------------------------
-2004-12-17 16:42:42 Typ=13 Len=8: 44,248,12,17,16,42,42,0


SQL> select dump(to_date('-1-1-1', 'syyyy-mm-dd')) from dual;


DUMP(TO_DATE('-1-1-1','SYYYY-MM-D
---------------------------------
Typ=13 Len=8: 255,255,1,1,0,0,0,0





对于公元前的日期,Oracle从255,255开始保存。公元前的年的保存的值和对应的公元后的年的值相加的和是256,255。如上例中的公元2004年和公元前2004年的值相加:212+44=256,7+248=255。

SQL中DATE类型最后还包括一个0,似乎目前没有使用。

出自:http://blog.itpub.net/post/468/10582

 
分享到:
评论

相关推荐

    oracle基本数据类型存储格式浅析.pdf

    ### Oracle基本数据类型存储格式浅析 —— 字符类型 #### 概述 在Oracle数据库中,字符类型是非常常见的数据类型之一,它主要用于存储文本信息。本文将详细探讨Oracle数据库中几种基本字符类型的存储格式,包括`...

    oracle基本数据类型

    Oracle 中有多种基本数据类型,包括字符类型、数字类型、日期类型、二进制类型等。了解这些数据类型的特点和使用场景,对于数据库设计和开发至关重要。本文将详细介绍 Oracle 中的基本数据类型,并讨论它们的特点和...

    oracle新手入门指导之四——ORACLE数据类型 .txt

    ### Oracle新手入门指导之四——ORACLE数据类型 在Oracle数据库中,数据类型的选择对于确保数据的正确存储、处理效率以及资源的有效利用至关重要。本文将详细介绍Oracle中的各种数据类型及其特性,帮助初学者更好地...

    Oracle 中表数据的存储原理浅析

    ### Oracle中表数据的存储原理浅析 #### 1. 引言 在Oracle数据库中,当用户创建一个表时,Oracle会自动在相应的表空间内为此表分配数据段以容纳其数据。用户可以通过多种方式控制数据段的空间分配与使用: - 通过...

    Oracle基本数据类型.pdf

    ### Oracle基本数据类型详解 #### 一、概述 Oracle 数据库提供了多种数据类型来满足不同的需求,这些数据类型包括字符型、数值型、日期时间型、大对象类型等。了解这些基本数据类型对于正确设计数据库表结构至关...

    Oracle基本数据类型

    以下是关于Oracle基本数据类型的详细说明: 1. **Char(n)**:这是一个定长字符串数据类型,长度可设置为1到2000字节。无论实际存储的数据是否占满指定长度,Oracle都会分配足够的空间。如果未指定长度,默认为1个...

    Oracle与.Net 数据类型映射

    了解Oracle数据库与.NET数据类型的映射关系对于开发人员来说至关重要,这直接影响到数据的正确存储、检索和处理。以下是对"Oracle与.Net 数据类型映射"这一主题的详细解释。 首先,Oracle数据库提供了一系列的数据...

    oracle日期时间数据类型与时间间隔数据类型讲解

    ### Oracle日期时间数据类型与时间间隔数据类型详解 #### 23.1 概述:Oracle中的日期时间数据类型 在Oracle数据库中,日期时间数据类型主要包括`DATE`、`TIMESTAMP`及其变体(如`TIMESTAMP WITH TIME ZONE`、`...

    oracle基本数据类型及用法

    在开始学习数据库时,理解Oracle的基本数据类型及其用法至关重要。以下是对Oracle数据类型的详细解释: 1. **字符型数据类型**: - **CHAR**: 用于存储固定长度的文本数据,如果输入的数据不足指定长度,Oracle会...

    Oracle 数据类型及存储方式.pdf

    Oracle数据库支持多种数据类型,包括数值型、字符型、日期时间型和LOB等大对象数据类型,每种数据类型都有其特定的存储需求和方式。 首先,数值型数据类型,比如INT, NUMBER等,用于存储数字信息。在Oracle中,数字...

    java、mysql以及oracle数据类型对照表

    MySQL和Oracle的数据类型则针对存储和操作数据库中的各种数据类型进行了优化。 MySQL的数据类型包括数值类型(如INT、DECIMAL)、字符串类型(如VARCHAR、TEXT)、日期和时间类型(如DATE、TIMESTAMP)以及二进制...

    Oracle与DB2数据类型分类对应说明

    在本文中,我们将对 Oracle 和 DB2 的数据类型进行分类和对应说明,主要包括数值类型、日期时间类型、字符串类型、LOB 类型和 ROWID 类型等。 一、数值类型 Oracle 中的 NUMBER 类型可以对应 DB2/400 中的多种类型...

    oracle和sql数据类型

    Oracle 和 SQL 数据类型是数据库管理系统中用于定义和存储数据的基础组件。它们决定了数据的结构、大小以及如何进行处理。以下是两种数据库系统中主要数据类型的详细比较: **Oracle 数据类型** 1. **Char**: Char...

    Oracle各种数据类型的介绍,适合中高级编程开发人员

    ### Oracle 数据类型详解 在数据库管理系统(DBMS)中,数据类型是定义字段或变量能够存储何种类型数据的标准。Oracle数据库提供了丰富的数据类型,适用于不同的应用场景。本文将详细介绍Oracle中的几种常见数据...

    Oracle日期型数据格式

    本文介绍了Oracle中日期型数据格式的相关知识,包括如何设置日期格式以及如何使用`TO_DATE()`和`TO_CHAR()`函数进行日期类型的转换。理解这些基础知识对于日常的数据库管理和开发工作至关重要。通过合理地设置和利用...

    sql server 和oracle 中数据类型的区别

    5. **datetime**: 存储日期和时间信息,SQL Server中`datetime`类型占用8个字节,Oracle中的对应类型为`DATE`。 6. **decimal**: 存储十进制数,如`decimal(9)`,在Oracle中对应`NUMBER(18)`。 7. **float**: 浮点数...

Global site tag (gtag.js) - Google Analytics