Oracle全球化 —— 时间类型、时区与时间相关函数

最近遇到一个表中数据时区不对的问题,排查思路一般是看表字段类型、看时区以及看插入时间的方法。Oracle官方文档《Database Globalization Support Guide》里有很详细的介绍,归纳学习一下。

 

一、 时间类型

Oracle里的时间类型分两大类 —— Datetime 和 Interval Data Types,本文主要关注第一类Datetime。

Datetime又可以分为四类,其中与时区有关的是后两类:

  • DATE
  • TIMESTAMP
  • TIMESTAMP WITH TIME ZONE
  • TIMESTAMP WITH LOCAL TIME ZONE

 

1. DATE

存储日期+时间,精确到秒,不存储时区和地区信息。输出格式和语言由 NLS_DATE_FORMAT和NLS_DATE_LANGUAGE 两个初始化参数决定。如果查询时不指定这两个参数也不进行类型转换,会按默认格式输出。

SQL> select sysdate from dual;

SYSDATE
-------------------
2014-02-12 01:12:18

2. TIMESTAMP

DATE类型的扩展,存储日期+时间,可精确到秒后0~9位小数点(默认是6),也不存储时区和地区信息。输出格式和语言由 NLS_TIMESTAMP_FORMAT和NLS_DATE_LANGUAGE 两个初始化参数决定。如果查询时不指定这两个参数也不进行类型转换,会按默认格式输出。

SQL> select localtimestamp from dual;

LOCALTIMESTAMP
---------------------------------------------------------------------------
12-FEB-14 01.14.12.945256 AM

SQL> alter session set nls_timestamp_format='YYYY-MM-DD HH24:MI:SSXFF';
Session altered.

SQL> select localtimestamp from dual;

LOCALTIMESTAMP
---------------------------------------------------------------------------
2014-02-12 01:28:31.652888

3. TIMESTAMP WITH TIME ZONE

TIMESTAMP类型的扩展,存储日期+时间,可精确到秒后0~9位小数点(默认是6),存储时区(或时区和地区)信息此类型的数据在保存到数据库时带有当前客户端的session timezone,无论在什么时区查看这些数据,数据都不会随时区而变化。

create table t1 (id number,time timestamp with time zone);  --创建t1表,其中time 列的数据类型是timestamp with time zone
Table created.

select sessiontimezone from dual; --当前客户端的session timezone 是 -8:00
SESSIONTIMEZONE
---------------------------------------------------------------------------
-08:00

insert into t1 values(1,timestamp '2014-02-12 02:00:00');  --向t1表中插入一条数据  
1 row created.

select * from t1;  --查看t1表,其中time列带时区显示,并且时区为数据被插入时的session timezone
        ID     TIME
----------   ---------------------------------------------------------------------------
         1     2014-02-12 02:00:00.000000 -08:00

alter session set time_zone='-6:00';  --修改当前客户端的session timezone为 -6:00
Session altered.

select * from t1;    --再次查看t1表,其中time列数据无变化
        ID     TIME
----------   ---------------------------------------------------------------------------
         1     2014-02-12 02:00:00.000000 -08:00

4. TIMESTAMP WITH LOCAL TIME ZONE

TIMESTAMP类型的另一种扩展,存储日期+时间,可精确到秒后0~9位小数点(默认是6),不存储时区信息,而是将客户端输入的时间基于database timezone转换后存入数据库(这也就是database tmiezone设置的意义所在,作为TIMESTAMP WITH LOCAL TIME ZONE类型的计算标尺)。当用户查询此类型数据时,Oracle会把数据再转为用户session的时区时间返回给用户。

客户端A时区时间 -> 数据库database tmiezone设置的时区时间 -> 客户端B时区时间

create table t2(id number,time timestamp with local time zone);  -- 创建t2表,其中time列为TIMESTAMP WITH LOCAL TIME ZONE
Table created.

insert into t2 values(1,timestamp '2014-02-12 02:10:00 -8:00');  --在t2表插入数据指定时区为-8:00,实际在保存到数据库时转化为基于database timezone的时间保存    
1 row created. 

select sessiontimezone from dual;  --当前客户端的session timezone 为 -6:00
SESSIONTIMEZONE
---------------------------------------------------------------------------
-06:00

select * from t2;  --查看时oracle将数据转换成当前客户端session timezone的时间
        ID      TIME
----------   ---------------------------------------------------------------------------
         1       2014-02-12 04:10:00.000000

5. 时间类型的选择

  • DATE:需要的时间精度不高,不需要保存时区/地区信息
  • TIMESTAMP:需要的时间精度高,不需要保存时区/地区信息
  • TIMESTAMP WITH TIME ZONE:需要保存时区/地区信息。比如需要精确记录每一笔交易的时间和地点(时区),看它是在当地几点发生的
  • TIMESTAMP WITH LOCAL TIME ZONE:不关心操作发生的地点,只关心操作是在你当前所在时区几点发生的。比如有一部电视剧在日本时间十点开播,但其实我只关心在中国时间几点能一起追直播,对我来说最方便的就是一查数据库直接告诉我它在中国时间九点开播。

二、 时区

其实根据前面一节已经知道了,Oracle时区分两种 —— 数据库时区和会话时区

1. 数据库时区

作为TIMESTAMP WITH LOCAL TIME ZONE类型的计算标尺。

查询方法

SELECT dbtimezone FROM DUAL;

设置方法

  • 可以在CREATE DATABASE 时用 SET TIME_ZONE子句指定。
CREATE DATABASE db01
...
SET TIME_ZONE='Europe/London';
-- 或者
CREATE DATABASE db01
...
SET TIME_ZONE='-05:00';
  • 也可后期修改(重启DB生效)
ALTER DATABASE SET TIME_ZONE='Europe/London';
--或者
ALTER DATABASE SET TIME_ZONE='-05:00';

2. 会话时区

当前sql会话所在时区,默认是服务器操作系统所在时区。

查询方法

SELECT sessiontimezone FROM DUAL;

设置方法

  • 可以设置操作系统的 ORA_SDTZ 环境变量
setenv ORA_SDTZ 'OS_TZ'  #默认
setenv ORA_SDTZ 'DB_TZ'
setenv ORA_SDTZ 'Europe/London'
setenv ORA_SDTZ '-05:00'
  • 也可以用sql命令设置
ALTER SESSION SET TIME_ZONE=local; -- 相当于os
ALTER SESSION SET TIME_ZONE=dbtimezone;
ALTER SESSION SET TIME_ZONE='Asia/Hong_Kong';
ALTER SESSION SET TIME_ZONE='+10:00';

三、 时间相关函数

Datetime函数可操作 date (DATE), timestamp (TIMESTAMP, TIMESTAMP WITH TIME ZONE, TIMESTAMP WITH LOCAL TIME ZONE) 及 interval (INTERVAL DAY TO SECOND, INTERVAL YEAR TO MONTH) 类型的值。

 

1. Datetime Functions Designed for the DATE Data Type

Function Description

ADD_MONTHS

Returns the date d plus n months

LAST_DAY

Returns the last day of the month that contains date

MONTHS_BETWEEN

Returns the number of months between date1 and date2

NEW_TIME

Returns the date and time in zone2 time zone when the date and time in zone1 time zone are date

Note: This function takes as input only a limited number of time zones. You can have access to a much greater number of time zones by combining the FROM_TZ function and the datetime expression.

NEXT_DAY

Returns the date of the first weekday named by char that is later than date

ROUND(date)

Returns date rounded to the unit specified by the fmt format model

TRUNC(date)

Returns date with the time portion of the day truncated to the unit specified by the fmt format model

2. Additional Datetime Functions

Datetime Function Description

CURRENT_DATE

Returns the current date in the session time zone in a value in the Gregorian calendar, of the DATE data type

CURRENT_TIMESTAMP

Returns the current date and time in the session time zone as a TIMESTAMP WITH TIME ZONE value

DBTIMEZONE

Returns the value of the database time zone. The value is a time zone offset or a time zone region name

EXTRACT (datetime)

Extracts and returns the value of a specified datetime field from a datetime or interval value expression

FROM_TZ

Converts TIMESTAMP value at a time zone to a TIMESTAMP WITH TIME ZONE value

LOCALTIMESTAMP

Returns the current date and time in the session time zone in a value of the TIMESTAMP data type

NUMTODSINTERVAL

Converts number n to an INTERVAL DAY TO SECOND literal

NUMTOYMINTERVAL

Converts number n to an INTERVAL YEAR TO MONTH literal

SESSIONTIMEZONE

Returns the value of the current session's time zone

SYS_EXTRACT_UTC

Extracts the UTC from a datetime with time zone offset

SYSDATE

Returns the date and time of the operating system on which the database resides, taking into account the time zone of the database server's operating system that was in effect when the database was started

SYSTIMESTAMP

Returns the system date, including fractional seconds and time zone of the system on which the database resides

TO_CHAR (datetime)

Converts a datetime or interval value of DATETIMESTAMPTIMESTAMP WITH TIME ZONE, or TIMESTAMP WITH LOCAL TIME ZONE data type to a value of VARCHAR2 data type in the format specified by the fmt date format

TO_DSINTERVAL

Converts a character string of CHARVARCHAR2NCHAR, or NVARCHAR2 data type to a value of INTERVAL DAY TO SECOND data type

TO_NCHAR (datetime)

Converts a datetime or interval value of DATETIMESTAMPTIMESTAMP WITH TIME ZONETIMESTAMP WITH LOCAL TIME ZONEINTERVAL MONTH TO YEAR, or INTERVAL DAY TO SECOND data type from the database character set to the national character set

TO_TIMESTAMP

Converts a character string of CHARVARCHAR2NCHAR, or NVARCHAR2 data type to a value of TIMESTAMP data type

TO_TIMESTAMP_TZ

Converts a character string of CHARVARCHAR2NCHAR, or NVARCHAR2 data type to a value of the TIMESTAMP WITH TIME ZONE data type

TO_YMINTERVAL

Converts a character string of CHARVARCHAR2NCHAR, or NVARCHAR2 data type to a value of the INTERVAL YEAR TO MONTH data type

TZ_OFFSET

Returns the time zone offset that corresponds to the entered value, based on the date that the statement is executed

3. Time Zone Conversion Functions

Time Zone Function Description

ORA_DST_AFFECTED

Enables you to verify whether the data in a column is affected by upgrading the DST rules from one version to another version

ORA_DST_CONVERT

Enables you to upgrade your TSTZ column data from one version to another

ORA_DST_ERROR

Enables you to verify that there are no errors when upgrading a datetime value

参考

https://docs.oracle.com/en/database/oracle/oracle-database/19/nlspg/datetime-data-types-and-time-zone-support.html#GUID-7A1BA319-767A-43CC-A579-4DAC7063B243

http://blog.itpub.net/29457434/viewspace-1080444/

发布了295 篇原创文章 · 获赞 35 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/Hehuyi_In/article/details/104883708
今日推荐