目 录CONTENT

文章目录

【GaussDB】GaussDB506版本A模式中的date类型

DarkAthena
2026-01-25 / 0 评论 / 0 点赞 / 5 阅读 / 0 字

【GaussDB】GaussDB506版本A模式中的date类型

GuassDB 在506.0版本中引入了一个新的数据类型,datea,用于兼容ORACLE的date类型。而在此版本前,GaussDB只是在ORACL兼容模式下,把位于数据类型位置的date,转换成了timestamp(0) without timezone。虽然timestamp(0)和ORACLE的date都是精确到秒,但是两者仍有诸多差异。在边上修修补补对齐行为,还要考虑原本timestamp类型行为的对齐,存在很多矛盾。所以GaussDB干脆就直接新增了一个类型,不再折腾原本的timestamp了。

GaussDB官方文档: GaussDB文档中心/集中式版Oracle兼容性说明/兼容性说明/SQL的基本元素/数据类型

启用date默认映射到datea

修改参数mapping_date_to_datea=on,重启数据库,SQL解析时就会把date类型转换成datea类型。
注:新安装的506.0 SPC0100版本中,该参数是默认开启的。

影响点

  1. SQL中DATE类型的语义识别
    之前版本中,
create table t1(a date); -> create table t1(a timestamp(0) without time zone);
select cast(sysdate as date) -> select cast(sysdate as timestamp(0) without time zone);

启用datea后

create table t1(a date); -> create table t1(a datea);
select cast(sysdate as date) -> select cast(sysdate as datea);
  1. 默认输出的文本格式
gaussdb=# select '2022-01-01 22:01:23'::timestamp(6)::datea;
         datea          
------------------------
 2022-01-01 22:01:23 AD
(1 row)

gaussdb=# select trunc('2022-01-01 22:01:23'::timestamp(6)::datea);
         trunc          
------------------------
 2022-01-01 00:00:00 AD
(1 row)

gaussdb=# 

ORACLE里的DATE格式在sqlplus中的输出受会话中nls_date_format参数的影响,而gaussdb则为固定格式 。

相比自带的timestamp类型,秒后面没有小数了,但相比ORACLE的date类型,多了个表示公元前后的标识AD/BC,而ORACLE则是在前面加负号表示公元前(需alter session set nls_Date_format='syyyy-mm-dd hh24:mi:ss';才能显示)。

  1. 实际存储
gaussdb=# select timestamp_send('2022-01-01 22:01:23'::timestamp(6));
   timestamp_send   
--------------------
 \x0002778b326412c0
(1 row)

gaussdb=# select datea_send('2022-01-01 22:01:23'::timestamp(6)::datea);
     datea_send     
--------------------
 \x0002778b326412c0
(1 row)

可以发现datea的存储格式其实还是和timestamp类型一致,因此并不会因为不记录秒后小数而节省存储空间。

  1. 系统函数映射
  • sysdate
mapping_date_to_dateaa_format_dev_versiona_format_date_timestampsysdate实际表达式数据类型数据输出格式示例
ons7onsysdate_a()datea2025-06-13 11:00:44 AD
ons7offsysdate_a()datea2025-06-13 11:00:44 AD
ons1onsysdate_a()datea2025-06-13 11:00:44 AD
ons1offsysdate_a()datea2025-06-13 11:00:44 AD
offs7on(clock_timestamp())::timestamp(0) without time zonetimestamp2025-06-13 11:00:44.000000
offs7off(clock_timestamp())::timestamp(0) without time zonetimestamp2025-06-13 11:00:44.000000
offs2-s6on(pg_systimestamp())::timestamp(0) without time zonetimestamp2025-06-13 11:00:44.000000
offs2-s6off(pg_systimestamp())::timestamp(0) without time zonetimestamp2025-06-13 11:00:44.000000
offs1on(pg_systimestamp())::timestamp(0) without time zonetimestamp2025-06-13 11:00:44.000000
offs1off(pg_systimestamp())::timestamp(0) without time zonetimestamp2025-06-13 11:00:44.000000
  • current_date
mapping_date_to_dateaa_format_dev_versiona_format_date_timestampcurrent_date实际表达式数据类型数据输出格式示例
ons7onpg_systimestamp())::dateadatea2025-06-13 11:00:44 AD
ons7offpg_systimestamp())::dateadatea2025-06-13 11:00:44 AD
ons1onpg_systimestamp())::dateadatea2025-06-13 11:00:44 AD
ons1offpg_systimestamp())::dateadatea2025-06-13 11:00:44 AD
offs7on('now'::text)::timestamp(0) without time zonetimestamp2025-06-13 11:00:44.000000
offs7off('now'::text)::timestamp(0) without time zonetimestamp2025-06-13 11:00:44.000000
offs2-s6on('now'::text)::timestamp(0) without time zonetimestamp2025-06-13 11:00:44.000000
offs2-s6off('now'::text)::timestamp(0) without time zonetimestamp2025-06-13 11:00:44.000000
offs1on(pg_systimestamp())::timestamp(0) without time zonetimestamp2025-06-13 11:00:44.000000
offs1offtext_date('now'::text)"date"2025-06-13

映射到不同的函数,其查询结果的值会与事务、跨语句、执行次数等行为存在相关性,这是老生常谈的问题,本文暂不展开,可参考PG的文档或问AI。

  1. 部分表达式的行为变化
    开启后,默认情况下 date'2022-01-01' 这样的用法会报错,因为nls_date_format的默认值是DD-MON-RR,需要修改参数nls_date_format='yyyy-mm-dd'才能正常执行,这里和ORACLE产生了兼容性差异,ORACLE的 date'2022-01-01'这种用法与nls_date_format参数无关,只能使用syyyy-mm-dd的格式。
gaussdb=# select date'2022-12-13';
ERROR:  invalid value "22-12-13" for "MON"
LINE 1: select date'2022-12-13';
                   ^
DETAIL:  The given value did not match any of the allowed values for this field.
CONTEXT:  referenced column: datea
gaussdb=# set nls_date_format='yyyy-mm-dd';
SET
gaussdb=# select date'2022-12-13';
         datea          
------------------------
 2022-12-13 00:00:00 AD
(1 row)

gaussdb=# 
  1. 操作符变化
gaussdb=# select '2022-01-01 22:01:23'::timestamp(6)::datea -'2021-01-01 21:01:23'::timestamp(6)::datea;
     ?column?     
------------------
 365.041666666667
(1 row)

gaussdb=# select '2022-01-01 22:01:23'::timestamp(6) -'2021-01-01 21:01:23'::timestamp(6);
           ?column?            
-------------------------------
 +000000365 01:00:00.000000000
(1 row)

gaussdb=# 

最重要的就是两个日期相减了,原本的timestamp相减只能返回interval类型,而datea相减能返回numeric类型,行为兼容ORACLE。

  1. 数据导入
    原本timestamp可以直接以文本方式导入,开启后,对于datea类型必须指定datea_format格式(oracle的sqlldr也要指定日期格式)

  2. 函数易变性
    另外,还有一个参数 modify_function_property,新装的默认值为“3257,5562,4164,4073”,
    表示把下面这4个函数的易变性从immutable改成stable

  • pg_catalog.current_timestamp(numeric)
  • pg_catalog.text_timestamp(text)
  • pg_catalog.text_date(text)
  • pg_catalog.DBTimezone()

因为date相关的表达式在不同GUC参数配置下会对应到不同的表达式,而上面这些函数的易变性可以调整,就增加了影响结果的因素。

总结

如果习惯了之前openGauss/GaussDB版本把date处理成timestamp(0),则建议在506.0版本中关闭mapping_date_to_datea,因为这些行为变化实在太多了,可能现有应用程序代码要排查的点太多。但如果是刚开始使用这个版本,可以开启mapping_date_to_datea,这样至少日期相减得数字的这个最常见的兼容性问题就不用纠结了。

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin
博主关闭了所有页面的评论