- 浏览: 166666 次
- 性别:
- 来自: 南京
文章分类
- 全部博客 (327)
- JAVA (130)
- 工作笔记 (49)
- SQLSERVER (5)
- ORACLE (28)
- nginx (1)
- Unix C (16)
- 系统 (19)
- 网络技术 (17)
- WEB前端 (22)
- Eclipse (2)
- Tomcat (1)
- spring (7)
- MYSQL (12)
- Maven (6)
- JETTY (2)
- 设计 (2)
- 开源项目 (7)
- asterisk (0)
- C++ (2)
- WINDOWS (2)
- SCALA (0)
- 协议 (1)
- Netty (1)
- SHELL (1)
- mybaits (4)
- 并发 (2)
- 架构 (2)
- TCP/IP (8)
- 虚拟化 (3)
- 不要再说java慢 (0)
- mac (2)
- mysql乱码完美解决 (1)
最新评论
[url]http://www.net527.cn/shujukuguanli/Oracle/2010/0623/11647.html
[/url]
第三部分 日期时间类型 3.1 DATE Date类型Oralce用于表示日期和时间的数据类型。固定占用7个字节。 包括七个属性: 世纪 世纪中的年份 月份 月份中的哪一天 小时 分 秒 SQL create table test_date(col_date date); Table created SQL insert into test_date values(to_date('2008-06-27 10:35:00','yyyy-mm-dd hh24:mi:ss'))
第三部分 日期时间类型
§3.1 DATE
Date类型Oralce用于表示日期和时间的数据类型。固定占用7个字节。
包括七个属性:
世纪
世纪中的年份
月份
月份中的哪一天
小时
分
秒
SQL> create table test_date(col_date date);
Table created
SQL> insert into test_date values(to_date('2008-06-27 10:35:00','yyyy-mm-dd hh24:mi:ss'));
1 row inserted
SQL> select to_char(col_date,'yyyy-mm-dd hh24:mi:ss'),dump(col_date) from test_date;
TO_CHAR(COL_DATE,'YYYY-MM-DDHH DUMP(COL_DATE)
------------------------------ --------------------------------------------------------------------------------
2008-06-27 10:35:00 Typ=12 Len=7: 120,108,6,27,11,36,1
Date类型的内部编码为12
长度:占用7个字节
数据存储的每一位到第七位分别为:世纪,年,月,日,时,分,秒。
世纪:采用”加100”表示法来存储。即世纪+100来存储。120 – 100 = 20
年:跟世纪一样采用”加100”表示法来存储。108 – 100 = 08(采用两位表示)
月:自然存储.6
日:自然存储,不做修改,27
时:(时,分,秒都采用“加1”法存储)11 -1= 10
分:36 -1 = 35
秒:1 -1 = 0
为什么世纪和年份要用加100法存储呢?是为了支持BC和AD日期。
BC即为公元前。
AD即为公元。
如果世纪 – 100为一个负数,那么就是一个BC日期。
插入一个公元前日期
SQL> insert into test_date values(to_date('-4712-01-01','syyyy-mm-dd hh24:mi:ss'));
1 row inserted
SQL> select to_char(col_date,'bc yyyy-mm-dd hh24:mi:ss'),dump(col_date) from test_date;
TO_CHAR(COL_DATE,'BCYYYY-MM-DD DUMP(COL_DATE)
------------------------------ --------------------------------------------------------------------------------
公元 2008-06-27 10:35:00 Typ=12 Len=7: 120,108,6,27,11,36,1
公元前 4712-01-01 00:00:00 Typ=12 Len=7: 53,88,1,1,1,1,1
我们已经了解了日期的存储结构。当要对日期进行截取时,比如去掉时,分,秒。只需要把最后的三个字节设为:12 12 1就可以了。
SQL> create table test_date1 (col_char varchar2(12), col_date date);
Table created
SQL> insert into test_date1 values('full',to_date('2008-06-27 12:01:00','yyyy-mm-dd hh24:mi:ss'));
1 row inserted
SQL> insert into test_date1(col_char,col_date) select 'minute', trunc(col_date,'mi') from test_date1
2 union all
3 select 'day', trunc(col_date,'dd') from test_date1
4 union all
5 select 'month',trunc(col_date,'mm') from test_date1
6 union all
7 select 'year',trunc(col_date,'y') from test_date1
8 ;
4 rows inserted
SQL> select col_char, col_date,dump(col_date) from test_date1;
COL_CHAR COL_DATE DUMP(COL_DATE)
------------ ----------- --------------------------------------------------------------------------------
full 2008-6-27 1 Typ=12 Len=7: 120,108,6,27,13,2,1
minute 2008-6-27 1 Typ=12 Len=7: 120,108,6,27,13,2,1
day 2008-6-27 Typ=12 Len=7: 120,108,6,27,1,1,1
month 2008-6-1 Typ=12 Len=7: 120,108,6,1,1,1,1
year 2008-1-1 Typ=12 Len=7: 120,108,1,1,1,1,1
要把一个日期截取,只取到年。数据库只是把最后5个字节置上1。这是非常快的。
当我们对一个Date字段进行操作,需要截取到年份进行比较时,我们经常使用to_char函数。通过会这样写。
Select * from test_date1 where to_char(col_date ,’yyyy’) = ‘2008’
而不是
Select * from test_date1 where trunc(col_date,’y’) = to_date(‘2008-01-01’,’yyyy-mm-dd’)
使用trunc会占用更少的资源,性能更优。
使用to_char所有的CPU时间与trunc相差一个数量级,差不多10倍。因为to_char必须把日期转换成一个串,并利用当前系统所采用的 NLS来完成,然后执行一个串与串的比较。而TRUNC只需要把后5个字节设置为1,然后将两个7位的字节的二进行数进行比较就搞定了。所要截取一个 DATE列叶,应该避免使用to_char.
另外,要完全避免对DATE列应用函数。比如我们要查询2008年的所有数据,并且这一列上也有索引,我们希望能够用上这个索引。
SQL> select count(col_date) from test_date1 where col_date >= to_date('2008-01-01','yyyy-mm-dd') and col_date < to_date('2009-01-01','yyyy-mm-dd');
COUNT(COL_DATE)
---------------
5
§3.2 向Date类型增加或减时间
怎么向Date类型增加时间,例如:向Date增加1天,或1小时,或1秒,一月等。
常有的办法有几个方法:
a.向date增加一个NUMBER值。因为Date 加减操作是以天为单位。1秒就是 1/24/60/60。依此类推。
b.使用INTERVAL类型。后续会介绍
c.使用内置函数add_months增加月。增加月不像增加天那么简单,所以需要使用内置函数来处理。
3.2.1 增加秒
SQL> create table test_date2(id varchar2(10), operate_time date);
Table created
SQL> insert into test_date2 values('1',sysdate);
1 row inserted
SQL> select id, to_char(operate_time, 'yyyy-mm-dd hh24:mi:ss') from test_date2 where id=1;
ID TO_CHAR(OPERATE_TIME,'YYYY-MM-
---------- ------------------------------
1 2008-06-27 13:35:35
SQL> update test_date2 set operate_time = operate_time + 1/24/60/60 where id=1;
1 row updated
SQL> select id, to_char(operate_time, 'yyyy-mm-dd hh24:mi:ss') from test_date2 where id=1;
ID TO_CHAR(OPERATE_TIME,'YYYY-MM-
---------- ------------------------------
1 2008-06-27 13:35:36
3.2.2 增加分
SQL> update test_date2 set operate_time = operate_time + 1/24/60 where id=1;
1 row updated
SQL> select id, to_char(operate_time, 'yyyy-mm-dd hh24:mi:ss') from test_date2 where id=1;
ID TO_CHAR(OPERATE_TIME,'YYYY-MM-
---------- ------------------------------
1 2008-06-27 13:36:36
3.2.3 增加小时
SQL> update test_date2 set operate_time = operate_time + 1/24 where id=1;
1 row updated
SQL> select id, to_char(operate_time, 'yyyy-mm-dd hh24:mi:ss') from test_date2 where id=1;
ID TO_CHAR(OPERATE_TIME,'YYYY-MM-
---------- ------------------------------
1 2008-06-27 14:36:36
3.2.4 增加天
SQL> update test_date2 set operate_time = operate_time + 1 where id=1;
1 row updated
SQL> select id, to_char(operate_time, 'yyyy-mm-dd hh24:mi:ss') from test_date2 where id=1;
ID TO_CHAR(OPERATE_TIME,'YYYY-MM-
---------- ------------------------------
1 2008-06-28 14:36:36
3.2.4 增加周
SQL> update test_date2 set operate_time = operate_time + 1 * 7 where id=1;
1 row updated
SQL> select id, to_char(operate_time, 'yyyy-mm-dd hh24:mi:ss') from test_date2 where id=1;
ID TO_CHAR(OPERATE_TIME,'YYYY-MM-
---------- ------------------------------
1 2008-07-05 14:36:36
3.2.5 增加月
SQL> update test_date2 set operate_time = add_months(operate_time,1) where id=1;
1 row updated
SQL> select id, to_char(operate_time, 'yyyy-mm-dd hh24:mi:ss') from test_date2 where id=1;
ID TO_CHAR(OPERATE_TIME,'YYYY-MM-
---------- ------------------------------
1 2008-08-05 14:36:36
3.2.6 增加年
SQL> update test_date2 set operate_time = add_months(operate_time,1 * 12) where id=1;
1 row updated
SQL> select id, to_char(operate_time, 'yyyy-mm-dd hh24:mi:ss') from test_date2 where id=1;
ID TO_CHAR(OPERATE_TIME,'YYYY-MM-
---------- ------------------------------
1 2009-08-05 14:36:36
另外可以使用一个非常有用的函数NUMTODSINTERVAL来新增加小时,分钟,秒。
SQL> update test_date2 set operate_time = operate_time + numtodsinterval(1,'second') where id=1;
1 row updated
SQL> select id, to_char(operate_time, 'yyyy-mm-dd hh24:mi:ss') from test_date2 where id=1;
ID TO_CHAR(OPERATE_TIME,'YYYY-MM-
---------- ------------------------------
1 2009-08-05 14:36:37
Numtodsinterval(n, 'second') 获得秒的时间间隔
Numtodsinterval(n, 'minute') 获得分的时间间隔
Numtodsinterval(n, 'month') 获得月的时间间隔
Numtodsinterval(n, 'year') 获得月的时间间隔
增加月份时要非常的小心,应该使用add_months函数。为什么呢?
比如当前日期为2000-2-29日。增加一个月得到的日期就应该是2000-3-31
如果只是简单的加30天或加31天,是无法实现的。所以必须使用add_months函数,它会自动来处理这种月末问题。对年份进行增加也会出现类似的问 题
§3.3 TIMESTAMP
TIMESTAMP是支持小数秒和时区的日期/时间类型。对秒的精确度更高。
3.3.1 TIMESTAM语法
TIMESTAMP(n)
N的取值为0~9.表示指定TIMESTAMP中秒的小数位数。N为可选。如果n为0,timestamp与date等价。
SQL> create table test_timestamp(col_date date, col_timestamp timestamp(0));
Table created
SQL> insert into test_timestamp values(sysdate,systimestamp);
1 row inserted
SQL> select dump(col_date) from test_timestamp;
DUMP(COL_DATE)
--------------------------------------------------------------------------------
Typ=12 Len=7: 120,108,6,27,17,8,37
SQL> select dump(col_timestamp) from test_timestamp;
DUMP(COL_TIMESTAMP)
--------------------------------------------------------------------------------
Typ=180 Len=7: 120,108,6,27,17,8,38
如果指定了保留小数位数,那情况就大不一样了。
SQL> create table test_timestamp1 (col_date date, col_timestamp timestamp(9));
Table created
SQL> insert into test_timestamp1 values(sysdate, systimestamp);
1 row inserted
SQL> select dump(col_date) from test_timestamp1;
DUMP(COL_DATE)
--------------------------------------------------------------------------------
Typ=12 Len=7: 120,108,6,27,17,36,40
SQL> select dump(col_timestamp) from test_timestamp1;
DUMP(COL_TIMESTAMP)
--------------------------------------------------------------------------------
Typ=180 Len=11: 120,108,6,27,17,36,40,17,249,15,24
现在可以看到timestamp(9)占用了11个字节的空间。后面额外的四个字节包括了小数秒数。
3.3.2 TIMESTAMP 相减
将两个Date相减的结果是一个number.而将两个timestamp相减的结果是一个INTERVAL值
SQL> create table test_timestamp2(time1 timestamp(9), time2 timestamp(9));
Table created
SQL> insert into test_timestamp2 values(to_timestamp('2008-06-29 01:02:01.100000','yyyy-mm-dd hh24:mi:ss.ff'),to_timestamp('2008-07-29 02:03:02.000000','yyyy-mm-dd hh24:mi:ss.ff'))
2 ;
1 row inserted
SQL> select time2 - time1 from test_timestamp2;
TIME2-TIME1
---------------------------------------
+000000030 01:01:00.900000000
结果表示两个时间之间相隔的天数,小时数,分数,秒数.
相差30天1小时1分0.9秒
有时我们需要得到两个时间之前相关的年数和月数.
SQL> select numtoyminterval(months_between(time2,time1),'month') years_months, time2 -
2 add_months(time1 , trunc(months_between(time2,time1))) days_hours from test_timestamp2;
YEARS_MONTHS DAYS_HOURS
--------------------------------------- ---------------------------------------
+000000000-01 +000000000 01:01:01.000000000
在计算时,分,秒间隔时我们注意到,使用add_months之后,小数秒就丢掉了.
如果要保留集小数秒,我们就需要使用numtoyminterval函数
SQL> select numtoyminterval(months_between(time2,time1),'month') years_months, time2 -(time1 + numtoyminterval(trunc(months_between(time2,time1)),'month')) day_hours from test_timestamp2;
YEARS_MONTHS DAY_HOURS
--------------------------------------- ---------------------------------------
+000000000-01 +000000000 01:01:00.900000000
§3.4 TIMESTAMP WITH TIME ZONE
TIMESTAMP WITH TIME ZONE类型是TIMESTAMP的子类型,增加了时区支持。
SQL> create table test_timezone(col_ts timestamp, col_tz timestamp with time zone);
Table created
SQL> insert into test_timezone values(systimestamp, systimestamp);
1 row inserted
SQL> select dump(col_tz) from test_timezone;
DUMP(COL_TZ)
--------------------------------------------------------------------------------
Typ=181 Len=13: 120,108,6,27,9,55,24,43,209,96,112,28,60
SQL> select dump(col_ts) from test_timezone;
DUMP(COL_TS)
--------------------------------------------------------------------------------
Typ=180 Len=11: 120,108,6,27,17,55,24,43,209,96,112
占用13字节的存储空间,最后两位用于保存时区信息。
在timestamp类型中,对时,分,秒的存储采用了加1法。
在timestamp with time zone上执行timestamp运算时,oracle自动把两个类型首先转换为UTC时间,然后再执行运算。
§3.5 TIMESTAMP WITH LOCAL TIME ZONE
这个类型保存进数据库时会先转换成数据库时区再进行保存.
SQL> create table test_timeltz(col_date date, timetz timestamp with time zone, timeltz timestamp with local time zone);
Table created
SQL> insert into test_timeltz values(timestamp'2008-06-29 12:03:22.111 US/Pacific',timestamp'2008-06-29 12:03:22.111 US/Pacific',timestamp'2008-06-29 12:03:22.111 US/Pacific');
1 row inserted
SQL> select dbtimezone from dual;
DBTIMEZONE
----------
+08:00
SQL> select * from test_timeltz;
COL_DATE TIMETZ TIMELTZ
----------- -------------------------------------------------------------------------------- --------------------------------------------------------------------------------
2008-6-29 1 2008-06-29 12:03:22.111000 US/PACIFIC 2008-06-30 03:03:22.111000
SQL> select dump(col_date), dump(timetz), dump(timeltz) from test_timeltz;
DUMP(COL_DATE) DUMP(TIMETZ) DUMP(TIMELTZ)
-------------------------------------------------------------------------------- -------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Typ=12 Len=7: 120,108,6,29,13,4,23 Typ=181 Len=13: 120,108,6,29,20,4,23,6,157,185,192,137,156 Typ=231 Len=11: 120,108,6,30,4,4,23,6,157,185,192
请注意:
第一列,类型为date,只存储了日期和时间.时区和小数秒已经丢失了.不会执行时区转换.
第二列:类型为timestamp with time zone.保留了时区信息.并规范化了该时区相应的UTC时间.
第三列:类型为timestamp with local time zone.进行了转换,把插入的时间转为了数据库时区的时间.
timestamp with local time zone也是不需要记录时区信息的.它占用7-11个字节.
一旦你的数据表中有一列使用了timestamp with local time zone,你就不能再改变数据库时区.
通用协调时(UTC, Universal Time Coordinated) ,UTC与格林尼治平均时(GMT, Greenwich Mean Time)一样,都与英国伦敦的本地时相同. 北京时区是东八区,领先UTC八个小时
§3.6 INTERVAL
用于表示一段时间或一个时间间隔的方法.在前面有多次提过.INTERVAL有两种类型.
YEAR TO MONTH 能存储年或月指定的一个时间段.
DATE TO SECOND存储天,小时,分钟,秒指定的时间段.
在前面用到的两个函数numtoyminterval 和numtodsinterval就是创建interval最好的方法.
另外extract 函数可以很容易的获得时间的每个部分.
SQL> select extract(day from time2-time1) day, extract(hour from time2 - time1) hour,
2 extract (minute from time2 - time1) minute,extract (second from time2 - time1) second from
3 test_timestamp2;
DAY HOUR MINUTE SECOND
---------- ---------- ---------- ----------
30 1 1 0.9
3.6.1 Interval year to month
语法:
Interval year(n) to month
N表示年数的位数.取值:0~9 .默认为2,表示年数为0 ~ 99
如果要产生一个1年2个月的时间段.用numtoyminterval是最方便的.
SQL> select (numtoyminterval(1,'year') + numtoyminterval(2,'month')) yminterval from dual;
YMINTERVAL
---------------------------------------
+000000001-02
或者是:
SQL> select numtoyminterval(1 * 12 + 2,'month') yminterval from dual;
YMINTERVAL
---------------------------------------
+000000001-02
另外可以使用 to_yminterval(‘1-2’)函数来进行转换.
SQL> create table test_intervarym(col_interval interval year to month);
Table created
SQL> insert into test_intervarym values ( numtoyminterval(1 * 12 + 2,'month'));
1 row inserted
SQL> select * from test_intervarym;
COL_INTERVAL
---------------------------------------
+01-02
SQL> select dump(col_interval) from test_intervarym;
DUMP(COL_INTERVAL)
--------------------------------------------------------------------------------
Typ=182 Len=5: 128,0,0,1,62
INTERVAL year to month 采用固定5个字节进行存储.最后一位为天数值.采用加60算法.所以计算是需要减去60.
第一位为标志位,标志是否为正负数.
第二到第四位表示年数.
第五位表示日数
3.6.2 INTERVAL DAY TO SECOND
定义如下:
INTERVAL DAY(n) to second(m)
N为可选位数,表示天数的位数.可取值0~9,默认为2位.
M是秒字段小时的位数.取值0~9,默认为6
SQL> create table test_intervalds(col_ds interval day(9) to second(9));
Table created
SQL> insert into test_intervalds values(numtodsinterval(1,'second'));
1 row inserted
SQL> insert into test_intervalds values(numtodsinterval(1.000000001,'second'));
1 row inserted
SQL> select col_ds, dump(col_ds) from test_intervalds;
COL_DS DUMP(COL_DS)
--------------------------------------- --------------------------------------------------------------------------------
+000000000 00:00:01.000000000 Typ=183 Len=11: 128,0,0,0,60,60,61,128,0,0,0
+000000000 00:00:01.000000001 Typ=183 Len=11: 128,0,0,0,60,60,61,128,0,0,1
可见,这种类型也是采用固定11个字节来存储的.
第一位为标志位,区分正负数
第二到第四位表示天数.
第五位表示小时数.时,分,秒采用加60算法
第六位表示分钟数,
第七位表示秒数.
最后四位表示小数秒数.
[/url]
第三部分 日期时间类型 3.1 DATE Date类型Oralce用于表示日期和时间的数据类型。固定占用7个字节。 包括七个属性: 世纪 世纪中的年份 月份 月份中的哪一天 小时 分 秒 SQL create table test_date(col_date date); Table created SQL insert into test_date values(to_date('2008-06-27 10:35:00','yyyy-mm-dd hh24:mi:ss'))
第三部分 日期时间类型
§3.1 DATE
Date类型Oralce用于表示日期和时间的数据类型。固定占用7个字节。
包括七个属性:
世纪
世纪中的年份
月份
月份中的哪一天
小时
分
秒
SQL> create table test_date(col_date date);
Table created
SQL> insert into test_date values(to_date('2008-06-27 10:35:00','yyyy-mm-dd hh24:mi:ss'));
1 row inserted
SQL> select to_char(col_date,'yyyy-mm-dd hh24:mi:ss'),dump(col_date) from test_date;
TO_CHAR(COL_DATE,'YYYY-MM-DDHH DUMP(COL_DATE)
------------------------------ --------------------------------------------------------------------------------
2008-06-27 10:35:00 Typ=12 Len=7: 120,108,6,27,11,36,1
Date类型的内部编码为12
长度:占用7个字节
数据存储的每一位到第七位分别为:世纪,年,月,日,时,分,秒。
世纪:采用”加100”表示法来存储。即世纪+100来存储。120 – 100 = 20
年:跟世纪一样采用”加100”表示法来存储。108 – 100 = 08(采用两位表示)
月:自然存储.6
日:自然存储,不做修改,27
时:(时,分,秒都采用“加1”法存储)11 -1= 10
分:36 -1 = 35
秒:1 -1 = 0
为什么世纪和年份要用加100法存储呢?是为了支持BC和AD日期。
BC即为公元前。
AD即为公元。
如果世纪 – 100为一个负数,那么就是一个BC日期。
插入一个公元前日期
SQL> insert into test_date values(to_date('-4712-01-01','syyyy-mm-dd hh24:mi:ss'));
1 row inserted
SQL> select to_char(col_date,'bc yyyy-mm-dd hh24:mi:ss'),dump(col_date) from test_date;
TO_CHAR(COL_DATE,'BCYYYY-MM-DD DUMP(COL_DATE)
------------------------------ --------------------------------------------------------------------------------
公元 2008-06-27 10:35:00 Typ=12 Len=7: 120,108,6,27,11,36,1
公元前 4712-01-01 00:00:00 Typ=12 Len=7: 53,88,1,1,1,1,1
我们已经了解了日期的存储结构。当要对日期进行截取时,比如去掉时,分,秒。只需要把最后的三个字节设为:12 12 1就可以了。
SQL> create table test_date1 (col_char varchar2(12), col_date date);
Table created
SQL> insert into test_date1 values('full',to_date('2008-06-27 12:01:00','yyyy-mm-dd hh24:mi:ss'));
1 row inserted
SQL> insert into test_date1(col_char,col_date) select 'minute', trunc(col_date,'mi') from test_date1
2 union all
3 select 'day', trunc(col_date,'dd') from test_date1
4 union all
5 select 'month',trunc(col_date,'mm') from test_date1
6 union all
7 select 'year',trunc(col_date,'y') from test_date1
8 ;
4 rows inserted
SQL> select col_char, col_date,dump(col_date) from test_date1;
COL_CHAR COL_DATE DUMP(COL_DATE)
------------ ----------- --------------------------------------------------------------------------------
full 2008-6-27 1 Typ=12 Len=7: 120,108,6,27,13,2,1
minute 2008-6-27 1 Typ=12 Len=7: 120,108,6,27,13,2,1
day 2008-6-27 Typ=12 Len=7: 120,108,6,27,1,1,1
month 2008-6-1 Typ=12 Len=7: 120,108,6,1,1,1,1
year 2008-1-1 Typ=12 Len=7: 120,108,1,1,1,1,1
要把一个日期截取,只取到年。数据库只是把最后5个字节置上1。这是非常快的。
当我们对一个Date字段进行操作,需要截取到年份进行比较时,我们经常使用to_char函数。通过会这样写。
Select * from test_date1 where to_char(col_date ,’yyyy’) = ‘2008’
而不是
Select * from test_date1 where trunc(col_date,’y’) = to_date(‘2008-01-01’,’yyyy-mm-dd’)
使用trunc会占用更少的资源,性能更优。
使用to_char所有的CPU时间与trunc相差一个数量级,差不多10倍。因为to_char必须把日期转换成一个串,并利用当前系统所采用的 NLS来完成,然后执行一个串与串的比较。而TRUNC只需要把后5个字节设置为1,然后将两个7位的字节的二进行数进行比较就搞定了。所要截取一个 DATE列叶,应该避免使用to_char.
另外,要完全避免对DATE列应用函数。比如我们要查询2008年的所有数据,并且这一列上也有索引,我们希望能够用上这个索引。
SQL> select count(col_date) from test_date1 where col_date >= to_date('2008-01-01','yyyy-mm-dd') and col_date < to_date('2009-01-01','yyyy-mm-dd');
COUNT(COL_DATE)
---------------
5
§3.2 向Date类型增加或减时间
怎么向Date类型增加时间,例如:向Date增加1天,或1小时,或1秒,一月等。
常有的办法有几个方法:
a.向date增加一个NUMBER值。因为Date 加减操作是以天为单位。1秒就是 1/24/60/60。依此类推。
b.使用INTERVAL类型。后续会介绍
c.使用内置函数add_months增加月。增加月不像增加天那么简单,所以需要使用内置函数来处理。
3.2.1 增加秒
SQL> create table test_date2(id varchar2(10), operate_time date);
Table created
SQL> insert into test_date2 values('1',sysdate);
1 row inserted
SQL> select id, to_char(operate_time, 'yyyy-mm-dd hh24:mi:ss') from test_date2 where id=1;
ID TO_CHAR(OPERATE_TIME,'YYYY-MM-
---------- ------------------------------
1 2008-06-27 13:35:35
SQL> update test_date2 set operate_time = operate_time + 1/24/60/60 where id=1;
1 row updated
SQL> select id, to_char(operate_time, 'yyyy-mm-dd hh24:mi:ss') from test_date2 where id=1;
ID TO_CHAR(OPERATE_TIME,'YYYY-MM-
---------- ------------------------------
1 2008-06-27 13:35:36
3.2.2 增加分
SQL> update test_date2 set operate_time = operate_time + 1/24/60 where id=1;
1 row updated
SQL> select id, to_char(operate_time, 'yyyy-mm-dd hh24:mi:ss') from test_date2 where id=1;
ID TO_CHAR(OPERATE_TIME,'YYYY-MM-
---------- ------------------------------
1 2008-06-27 13:36:36
3.2.3 增加小时
SQL> update test_date2 set operate_time = operate_time + 1/24 where id=1;
1 row updated
SQL> select id, to_char(operate_time, 'yyyy-mm-dd hh24:mi:ss') from test_date2 where id=1;
ID TO_CHAR(OPERATE_TIME,'YYYY-MM-
---------- ------------------------------
1 2008-06-27 14:36:36
3.2.4 增加天
SQL> update test_date2 set operate_time = operate_time + 1 where id=1;
1 row updated
SQL> select id, to_char(operate_time, 'yyyy-mm-dd hh24:mi:ss') from test_date2 where id=1;
ID TO_CHAR(OPERATE_TIME,'YYYY-MM-
---------- ------------------------------
1 2008-06-28 14:36:36
3.2.4 增加周
SQL> update test_date2 set operate_time = operate_time + 1 * 7 where id=1;
1 row updated
SQL> select id, to_char(operate_time, 'yyyy-mm-dd hh24:mi:ss') from test_date2 where id=1;
ID TO_CHAR(OPERATE_TIME,'YYYY-MM-
---------- ------------------------------
1 2008-07-05 14:36:36
3.2.5 增加月
SQL> update test_date2 set operate_time = add_months(operate_time,1) where id=1;
1 row updated
SQL> select id, to_char(operate_time, 'yyyy-mm-dd hh24:mi:ss') from test_date2 where id=1;
ID TO_CHAR(OPERATE_TIME,'YYYY-MM-
---------- ------------------------------
1 2008-08-05 14:36:36
3.2.6 增加年
SQL> update test_date2 set operate_time = add_months(operate_time,1 * 12) where id=1;
1 row updated
SQL> select id, to_char(operate_time, 'yyyy-mm-dd hh24:mi:ss') from test_date2 where id=1;
ID TO_CHAR(OPERATE_TIME,'YYYY-MM-
---------- ------------------------------
1 2009-08-05 14:36:36
另外可以使用一个非常有用的函数NUMTODSINTERVAL来新增加小时,分钟,秒。
SQL> update test_date2 set operate_time = operate_time + numtodsinterval(1,'second') where id=1;
1 row updated
SQL> select id, to_char(operate_time, 'yyyy-mm-dd hh24:mi:ss') from test_date2 where id=1;
ID TO_CHAR(OPERATE_TIME,'YYYY-MM-
---------- ------------------------------
1 2009-08-05 14:36:37
Numtodsinterval(n, 'second') 获得秒的时间间隔
Numtodsinterval(n, 'minute') 获得分的时间间隔
Numtodsinterval(n, 'month') 获得月的时间间隔
Numtodsinterval(n, 'year') 获得月的时间间隔
增加月份时要非常的小心,应该使用add_months函数。为什么呢?
比如当前日期为2000-2-29日。增加一个月得到的日期就应该是2000-3-31
如果只是简单的加30天或加31天,是无法实现的。所以必须使用add_months函数,它会自动来处理这种月末问题。对年份进行增加也会出现类似的问 题
§3.3 TIMESTAMP
TIMESTAMP是支持小数秒和时区的日期/时间类型。对秒的精确度更高。
3.3.1 TIMESTAM语法
TIMESTAMP(n)
N的取值为0~9.表示指定TIMESTAMP中秒的小数位数。N为可选。如果n为0,timestamp与date等价。
SQL> create table test_timestamp(col_date date, col_timestamp timestamp(0));
Table created
SQL> insert into test_timestamp values(sysdate,systimestamp);
1 row inserted
SQL> select dump(col_date) from test_timestamp;
DUMP(COL_DATE)
--------------------------------------------------------------------------------
Typ=12 Len=7: 120,108,6,27,17,8,37
SQL> select dump(col_timestamp) from test_timestamp;
DUMP(COL_TIMESTAMP)
--------------------------------------------------------------------------------
Typ=180 Len=7: 120,108,6,27,17,8,38
如果指定了保留小数位数,那情况就大不一样了。
SQL> create table test_timestamp1 (col_date date, col_timestamp timestamp(9));
Table created
SQL> insert into test_timestamp1 values(sysdate, systimestamp);
1 row inserted
SQL> select dump(col_date) from test_timestamp1;
DUMP(COL_DATE)
--------------------------------------------------------------------------------
Typ=12 Len=7: 120,108,6,27,17,36,40
SQL> select dump(col_timestamp) from test_timestamp1;
DUMP(COL_TIMESTAMP)
--------------------------------------------------------------------------------
Typ=180 Len=11: 120,108,6,27,17,36,40,17,249,15,24
现在可以看到timestamp(9)占用了11个字节的空间。后面额外的四个字节包括了小数秒数。
3.3.2 TIMESTAMP 相减
将两个Date相减的结果是一个number.而将两个timestamp相减的结果是一个INTERVAL值
SQL> create table test_timestamp2(time1 timestamp(9), time2 timestamp(9));
Table created
SQL> insert into test_timestamp2 values(to_timestamp('2008-06-29 01:02:01.100000','yyyy-mm-dd hh24:mi:ss.ff'),to_timestamp('2008-07-29 02:03:02.000000','yyyy-mm-dd hh24:mi:ss.ff'))
2 ;
1 row inserted
SQL> select time2 - time1 from test_timestamp2;
TIME2-TIME1
---------------------------------------
+000000030 01:01:00.900000000
结果表示两个时间之间相隔的天数,小时数,分数,秒数.
相差30天1小时1分0.9秒
有时我们需要得到两个时间之前相关的年数和月数.
SQL> select numtoyminterval(months_between(time2,time1),'month') years_months, time2 -
2 add_months(time1 , trunc(months_between(time2,time1))) days_hours from test_timestamp2;
YEARS_MONTHS DAYS_HOURS
--------------------------------------- ---------------------------------------
+000000000-01 +000000000 01:01:01.000000000
在计算时,分,秒间隔时我们注意到,使用add_months之后,小数秒就丢掉了.
如果要保留集小数秒,我们就需要使用numtoyminterval函数
SQL> select numtoyminterval(months_between(time2,time1),'month') years_months, time2 -(time1 + numtoyminterval(trunc(months_between(time2,time1)),'month')) day_hours from test_timestamp2;
YEARS_MONTHS DAY_HOURS
--------------------------------------- ---------------------------------------
+000000000-01 +000000000 01:01:00.900000000
§3.4 TIMESTAMP WITH TIME ZONE
TIMESTAMP WITH TIME ZONE类型是TIMESTAMP的子类型,增加了时区支持。
SQL> create table test_timezone(col_ts timestamp, col_tz timestamp with time zone);
Table created
SQL> insert into test_timezone values(systimestamp, systimestamp);
1 row inserted
SQL> select dump(col_tz) from test_timezone;
DUMP(COL_TZ)
--------------------------------------------------------------------------------
Typ=181 Len=13: 120,108,6,27,9,55,24,43,209,96,112,28,60
SQL> select dump(col_ts) from test_timezone;
DUMP(COL_TS)
--------------------------------------------------------------------------------
Typ=180 Len=11: 120,108,6,27,17,55,24,43,209,96,112
占用13字节的存储空间,最后两位用于保存时区信息。
在timestamp类型中,对时,分,秒的存储采用了加1法。
在timestamp with time zone上执行timestamp运算时,oracle自动把两个类型首先转换为UTC时间,然后再执行运算。
§3.5 TIMESTAMP WITH LOCAL TIME ZONE
这个类型保存进数据库时会先转换成数据库时区再进行保存.
SQL> create table test_timeltz(col_date date, timetz timestamp with time zone, timeltz timestamp with local time zone);
Table created
SQL> insert into test_timeltz values(timestamp'2008-06-29 12:03:22.111 US/Pacific',timestamp'2008-06-29 12:03:22.111 US/Pacific',timestamp'2008-06-29 12:03:22.111 US/Pacific');
1 row inserted
SQL> select dbtimezone from dual;
DBTIMEZONE
----------
+08:00
SQL> select * from test_timeltz;
COL_DATE TIMETZ TIMELTZ
----------- -------------------------------------------------------------------------------- --------------------------------------------------------------------------------
2008-6-29 1 2008-06-29 12:03:22.111000 US/PACIFIC 2008-06-30 03:03:22.111000
SQL> select dump(col_date), dump(timetz), dump(timeltz) from test_timeltz;
DUMP(COL_DATE) DUMP(TIMETZ) DUMP(TIMELTZ)
-------------------------------------------------------------------------------- -------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Typ=12 Len=7: 120,108,6,29,13,4,23 Typ=181 Len=13: 120,108,6,29,20,4,23,6,157,185,192,137,156 Typ=231 Len=11: 120,108,6,30,4,4,23,6,157,185,192
请注意:
第一列,类型为date,只存储了日期和时间.时区和小数秒已经丢失了.不会执行时区转换.
第二列:类型为timestamp with time zone.保留了时区信息.并规范化了该时区相应的UTC时间.
第三列:类型为timestamp with local time zone.进行了转换,把插入的时间转为了数据库时区的时间.
timestamp with local time zone也是不需要记录时区信息的.它占用7-11个字节.
一旦你的数据表中有一列使用了timestamp with local time zone,你就不能再改变数据库时区.
通用协调时(UTC, Universal Time Coordinated) ,UTC与格林尼治平均时(GMT, Greenwich Mean Time)一样,都与英国伦敦的本地时相同. 北京时区是东八区,领先UTC八个小时
§3.6 INTERVAL
用于表示一段时间或一个时间间隔的方法.在前面有多次提过.INTERVAL有两种类型.
YEAR TO MONTH 能存储年或月指定的一个时间段.
DATE TO SECOND存储天,小时,分钟,秒指定的时间段.
在前面用到的两个函数numtoyminterval 和numtodsinterval就是创建interval最好的方法.
另外extract 函数可以很容易的获得时间的每个部分.
SQL> select extract(day from time2-time1) day, extract(hour from time2 - time1) hour,
2 extract (minute from time2 - time1) minute,extract (second from time2 - time1) second from
3 test_timestamp2;
DAY HOUR MINUTE SECOND
---------- ---------- ---------- ----------
30 1 1 0.9
3.6.1 Interval year to month
语法:
Interval year(n) to month
N表示年数的位数.取值:0~9 .默认为2,表示年数为0 ~ 99
如果要产生一个1年2个月的时间段.用numtoyminterval是最方便的.
SQL> select (numtoyminterval(1,'year') + numtoyminterval(2,'month')) yminterval from dual;
YMINTERVAL
---------------------------------------
+000000001-02
或者是:
SQL> select numtoyminterval(1 * 12 + 2,'month') yminterval from dual;
YMINTERVAL
---------------------------------------
+000000001-02
另外可以使用 to_yminterval(‘1-2’)函数来进行转换.
SQL> create table test_intervarym(col_interval interval year to month);
Table created
SQL> insert into test_intervarym values ( numtoyminterval(1 * 12 + 2,'month'));
1 row inserted
SQL> select * from test_intervarym;
COL_INTERVAL
---------------------------------------
+01-02
SQL> select dump(col_interval) from test_intervarym;
DUMP(COL_INTERVAL)
--------------------------------------------------------------------------------
Typ=182 Len=5: 128,0,0,1,62
INTERVAL year to month 采用固定5个字节进行存储.最后一位为天数值.采用加60算法.所以计算是需要减去60.
第一位为标志位,标志是否为正负数.
第二到第四位表示年数.
第五位表示日数
3.6.2 INTERVAL DAY TO SECOND
定义如下:
INTERVAL DAY(n) to second(m)
N为可选位数,表示天数的位数.可取值0~9,默认为2位.
M是秒字段小时的位数.取值0~9,默认为6
SQL> create table test_intervalds(col_ds interval day(9) to second(9));
Table created
SQL> insert into test_intervalds values(numtodsinterval(1,'second'));
1 row inserted
SQL> insert into test_intervalds values(numtodsinterval(1.000000001,'second'));
1 row inserted
SQL> select col_ds, dump(col_ds) from test_intervalds;
COL_DS DUMP(COL_DS)
--------------------------------------- --------------------------------------------------------------------------------
+000000000 00:00:01.000000000 Typ=183 Len=11: 128,0,0,0,60,60,61,128,0,0,0
+000000000 00:00:01.000000001 Typ=183 Len=11: 128,0,0,0,60,60,61,128,0,0,1
可见,这种类型也是采用固定11个字节来存储的.
第一位为标志位,区分正负数
第二到第四位表示天数.
第五位表示小时数.时,分,秒采用加60算法
第六位表示分钟数,
第七位表示秒数.
最后四位表示小数秒数.
发表评论
-
oracle 分页
2015-09-17 20:31 560SELECT * FROM (SELECT A.*, R ... -
Oracle IMPDP如何改变索引表空间
2015-08-11 13:22 901转自 http://blog.sina.com.cn/s/b ... -
批量造数据
2015-08-01 17:19 0CREATE OR REPLACE PROCEDURE ES_ ... -
11g归档
2015-03-23 22:31 409数据库归档 http://blog.sina.com.cn/s ... -
数据库压力测试
2015-03-21 22:04 549http://www.cnblogs.com/rootq/ar ... -
明天试试这个视图
2015-03-19 21:12 370V$SEGMENT_STATISTICS 用法 -
Oracle建立序列
2015-03-16 12:02 559create sequence hibernate_seq ... -
netstat 的使用
2015-03-09 16:48 493netstat -ltpe 查看当前活跃的连接 http:/ ... -
关于位图索引的帖子
2015-03-09 12:33 459http://www.itpub.net/thread-183 ... -
【转】Oracle 使用lock_sga和pre_page_sga参数保证SGA常驻物理内存
2015-03-09 11:33 515http://blog.csdn.net/laoshangxy ... -
视图的用法
2015-02-27 21:30 391关于视图的概念 http://blog.sina.com.cn ... -
oracle调优方法
2015-02-25 11:07 415一上午 10:36:13 这个东西需要看报表是吧? 大 ... -
ORACLE 伪列
2014-08-05 16:20 321多个不同的表要UNION在一起得出结果,为了统一输出结果,要用 ... -
表空间 用户 表
2014-04-24 16:48 3711. 创建一个表空间 create tablespace L ... -
ORACLE 分区
2013-10-26 17:52 591------------------------------- ... -
工作中用的两条查询语句,LEFT JOIN多张表的
2013-09-13 16:57 909----4G手机 left join 三张表 select a ... -
Split
2013-07-25 20:59 755CREATE OR REPLACE TYPE type_spl ... -
蒙昭良的博客地址.
2013-06-21 15:01 897http://space.itpub.net/12778571 ... -
Oracle 数据库用户管理
2013-06-21 14:57 406Oracle 数据库用户管理 Oracle 权限设置 一、权限 ... -
ORACLE中的五种约束
2013-06-21 13:48 836CREATE TABLE TABLENAMEEXAMLE( ...
相关推荐
在Oracle中,数据类型分为多种,包括字符类型、数值类型、日期时间类型、二进制类型、对象类型和其他特殊类型。 在Oracle中,字符类型主要包括CHAR、VARCHAR2和NCHAR、NVARCHAR2。CHAR是最基本的定长字符串类型,它...
Oracle数据库支持多种数据类型,包括数值型、字符型、日期时间型和LOB等大对象数据类型,每种数据类型都有其特定的存储需求和方式。 首先,数值型数据类型,比如INT, NUMBER等,用于存储数字信息。在Oracle中,数字...
以下是对Oracle数据类型及存储方式的深入探讨。 ### 第一部分:字符类型 #### §1.1 CHAR `CHAR`是一种固定长度的字符串类型,一旦定义了长度,如`CHAR(10)`,不论实际存储的数据是否达到这个长度,都会占用指定...
《Oracle基本数据类型存储格式详解》 Oracle数据库中,数据类型的存储格式对于数据库的性能和空间利用率至关重要。本文将深入探讨Oracle的字符类型、数字类型、日期类型、ROWID类型和RAW类型的基本数据类型的存储...
本文将深入探讨Oracle数据类型及其存储方式,帮助读者理解和掌握Oracle数据库的基础知识。 ### 第一部分:字符类型 #### §1.1 CHAR `CHAR`是一种固定长度的字符串类型,指定长度后,无论实际存储的字符数是多少...
### Oracle日期时间数据类型与时间间隔数据类型详解 ...以上就是Oracle数据库中关于日期时间数据类型及时间间隔数据类型的详细介绍。通过这些数据类型和相关的操作,可以高效地管理和处理日期时间数据。
Oracle 数据类型及存储方式是数据库设计中的核心概念,它们决定了数据如何在数据库中表示和存储。Oracle 提供了多种数据类型以适应各种不同类型的变量和字段。以下是对这些数据类型和存储方式的详细解释: **一、...
它提供了一个OracleDbType枚举,该枚举定义了所有Oracle数据类型到.NET数据类型的映射。例如,OracleDbType.Number对应.NET的decimal,OracleDbType.Varchar2对应.NET的string,OracleDbType.Date对应.NET的DateTime...
在Oracle数据库中,并不存在`datetime`这一数据类型,而是通过`date`类型来实现日期与时间的综合处理。`date`类型可以表示日期和时间,它固定占用7个字节的空间。本篇文章将详细介绍Oracle中的`date`类型以及其内部...
Oracle 中有多种基本数据类型,包括字符类型、数字类型、日期类型、二进制类型等。了解这些数据类型的特点和使用场景,对于数据库设计和开发至关重要。本文将详细介绍 Oracle 中的基本数据类型,并讨论它们的特点和...
标题"java、mysql以及oracle数据类型对照表"揭示了本主题的核心,即比较Java、MySQL和Oracle数据库的数据类型。Java的数据类型主要分为基本类型(如int、double、boolean)和引用类型(如类、接口和数组)。MySQL和...
- `bit`在SQL Server中没有直接对应的Oracle数据类型,但可以近似用单字节的`NUMBER(1)`表示。 - `datetime`和`smalldatetime`在SQL Server中对应Oracle的`DATE`,表示日期和时间。 - `decimal`和`numeric`在SQL ...
Oracle 数据类型是数据库管理系统Oracle中的核心元素,它们决定了如何存储和处理各种数据。在Oracle中,数据类型可以分为基本数据类型、对象数据类型和大型对象数据类型。以下是对Oracle主要数据类型的详细说明: 1...
在本文中,我们将对 Oracle 和 DB2 的数据类型进行分类和对应说明,主要包括数值类型、日期时间类型、字符串类型、LOB 类型和 ROWID 类型等。 一、数值类型 Oracle 中的 NUMBER 类型可以对应 DB2/400 中的多种类型...
在使用数据类型时,应根据实际需求选择合适的数据类型,比如字符数据的长度、数值的精度和范围,以及是否需要存储二进制或日期时间数据。在定义VARCHAR2和NVARCHAR2时,需注意它们的最大字节数限制,以及在UNICODE...
Oracle 提供了丰富的数据类型来满足各种数据存储需求,主要包括字符型、数值型、日期时间型和大对象型。 1. 字符型 字符型数据类型包括 `char(n)`, `varchar(n)` 和 `varchar2(n)`。`char(n)` 是固定长度的字符串,...
Oracle数据库中常用的数据类型主要包括字符类型、数字类型、日期时间类型以及LOB类型等,每一种数据类型适用于特定的数据存储需求。 1. 字符类型 - CHAR类型是固定长度的,用于存储定长的字符串,最多2000个字符。...
Oracle 和 SQL 数据类型是数据库管理系统中用于定义和存储数据的基础组件。它们决定了数据的结构、大小以及如何进行处理。以下是两种数据库系统中主要数据类型的详细比较: **Oracle 数据类型** 1. **Char**: Char...
Oracle 数据库是一个强大的关系型数据库管理系统,其丰富的数据类型和函数是进行数据存储和处理的基础。在Oracle中,数据类型用于定义字段可以存储的数据种类,而函数则帮助我们对数据进行各种操作。以下是对这些...