PostgreSQL时间戳与Oracle的不同

PG有两种时间戳:1、timestamp without time zone;2、timestamp with time zone;实际在内部存储上它们并没有什么不同。内部名字分别是timestamp和timestamptz(类型名字问题以前博文讲过,请自行阅读),OID分别是1114和1184。

它们的类型定义:

flying=# select typname,typlen,typstorage,typinput from pg_type where oid in (1114,1184);
   typname   | typlen | typstorage |    typinput
-------------+--------+------------+----------------
 timestamp   |      8 | p          | timestamp_in
 timestamptz |      8 | p          | timestamptz_in
(2 rows)

flying=#

都是8字节,保存的是微秒,内部定义是

typedef int64 Timestamp;
typedef int64 TimestampTz;
typedef int64 TimeOffset;
typedef int32 fsec_t;      /* fractional seconds (in microseconds) */

typedef struct
{
  TimeOffset  time;      /* all time units other than days, months and
                 * years */
  int32    day;      /* days, after time for alignment */
  int32    month;      /* months and years, after time for alignment */
} Interval;

前两个类型分别对应timestamp和timestamptz,最后一个Interval对应的是类型interval(其他文章提到interval类型的datum是指向数据的指针,就是它了)。

再来看输入函数 timestamptz_in(src/backend/utils/adt/timestamp.c),前边是语法分析(没错,这里嵌了个小语法分析器)解析字符串,如果输入格式是我们常见的诸如:2019-07-09 14:19:34.255 CST 指定时区,它会调用tm2timestamp,在这个函数里有一个根据时区做的调整 dt2local,也就是说最后存储的时间并没有记录输入的时区。

再来看Oracle,它有三种时间戳 1、timestamp without time zone;2、timestamp with time zone;3、timestamp with local time zone;

从文档来看,最后一种是不保存输入时区的,调整为数据库时区,其实这个类型更像PG的timestamp with time zone,而PG并没有类型能够对应Oralce的timestamp with time zone。

先体验一下Oracle下的操作

SQL> CREATE TABLE t(col1 TIMESTAMP WITH TIME ZONE);

表已创建。

SQL> desc t
 名称                                      是否为空? 类型
 ----------------------------------------- -------- ----------------------------

 COL1                                               TIMESTAMP(6) WITH TIME ZONE

SQL>

默认精度为6

SQL> INSERT INTO t VALUES('15-7月 -19 11.15.46.369000 上午 +08:00');

已创建 1 行。

SQL> INSERT INTO t VALUES('15-7月 -19 11.15.46.369000 上午 +09:00');

已创建 1 行。

SQL> SELECT * FROM t;

COL1
---------------------------------------------------------------------------
15-7月 -19 11.15.46.369000 上午 +08:00
15-7月 -19 11.15.46.369000 上午 +09:00

SQL>

PG里同样的操作:

flying=# CREATE TABLE t(col1 TIMESTAMP WITH TIME ZONE);
CREATE TABLE
flying=# show timezone;
 TimeZone
----------
 UTC
(1 row)
flying=# INSERT INTO t VALUES('2019-7-15 11:15:46.369000 +8');
INSERT 0 1
flying=# INSERT INTO t VALUES('2019-7-15 11:15:46.369000 +9');
INSERT 0 1
flying=# SELECT * FROM t;
            col1
----------------------------
 2019-07-15 03:15:46.369+00
 2019-07-15 02:15:46.369+00
(2 rows)

flying=# show timezone;
 TimeZone
----------
 UTC
(1 row)

插入数据本身的时区属性其实已经消失。

可以设想,如果有一个场景客户对每个输入时间的本地时间更感兴趣,希望查询时原样查出,PG一样可以应对,但明显要给应用开发端找些麻烦了。

自定义类型可以很好满足这个需求,不管是让PG内嵌,还是我们自行定义复合类型,都是可以的,有机会再演示。

转载于:https://my.oschina.net/quanzl/blog/3071551

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值