vlambda博客
学习文章列表

红象数据库兼容Oracle数据类型介绍

红象团队

https://gitee.com/redelephant2020/


红象数据库通过在内部兼容Oracle的数据类型来尽量减少数据和应用的迁移工作量,本文介绍了红象数据库目前已实现的Oracle数据类型,包括字符类型、数值类型、日期时间类型、时间间隔类型、raw、long等。类型相关的操作函数和集合类型、用户自定义类型等PLSQL数据类型将会在后面的文章中单独介绍。

字符类型

字符类型包括char、nchar、varchar2、nvarchar2,其中char和varchar2是语义相关的数据类型,在使用时可以指定类型的长度语义是字节或字符。如果在声明时没有显示的指定类型的长度语义,则同Oracle相同由nls_length_semantics参数决定字符数据类型的长度语义。

char和varchar2的语法如下:

char[(size[byte|char])]

varchar2(size[byte|char])

一个例子:

列col1和col2在定义时指定了长度语义,用户显示指定的“byte”和“char”修饰会覆盖“nls_length_semantics”参数指定的长度语义。col3没有指定长度语义,因此由nls_length_semantics参数决定。在\d查看表定义时当前的长度语义不显示。

在Oracle兼容模式下,空串被转换为NULL。

nchar和nvarchar2这是从语法上做了兼容,实际创建时替换为char和varchar2。未来可能会增加这两个数据类型。

数值类型

数值类型包括number、binary_float、binary_double,其中number类型目前只做了语法兼容和支持精度指定为星号(*)的用法,计划下一版本将完全兼容Oracle的number类型,包括标度大于精度、精度为负数等特殊用法。

示例:

红象数据库兼容Oracle数据类型介绍

日期时间类型

日期时间类型包括date、timestamp、timestamp with local time zone、timestamp with time zone,其中,timestamp with time zone目前版本只是语法兼容,并没有实际存储时区的值。

NLS参数:

  • nls_date_format

  • nls_timestamp_format

  • nls_timestamp_tz_format

date类型语法:

date

这个数据类型包含日期时间的年,月,日,时,分,秒域;没有小数秒和时区信息。

nls_date_format指定了date类型的显示格式,以及函数to_char和to_date使用的默认格式。

示例:

红象数据库兼容Oracle数据类型介绍

timestamp类型语法:

TIMESTAMP[(fractional_seconds_precision)]

timestamp数据类型是date类型的一个扩展,包含小数秒,它存储日期数据类型的年,月,日,加上时,分,秒的值。此数据类型用于存储精确的时间值,对于收集和计算跨地理区域的日期信息是有用的。可选参数fractional_seconds_precision指定了秒域中小数部分的位数,范围0~9,默认值为6。

nls_timestamp_format指定了timestamp类型的显示格式,以及to_char和to_timestamp函数使用的默认格式。

示例:

红象数据库兼容Oracle数据类型介绍

timestamp类型最多保留小数点后6位,超过采用四舍五入进位。这部分精度目前低于Oracle,因此使用时会给出warning信息提示。

示例:

红象数据库兼容Oracle数据类型介绍

timestamp with time zone类型语法:

TIMESTAMP[(fractional_seconds_precision)] WITH TIME ZONE

timestamp with time zone数据类型是timestamp类型的一个变种,除了包含timestamp类型的所有值外还包含时区信息,这个数据类型包含YEAR,MONTH,DAY,HOUR,MINUTE,SECOND,TIMEZONE_HOUR,和TIMEZONE_MINUTE。这个数据类型暂时不完全兼容Oracle的类型,除了小数秒精度范围外,其他与postgresql的timestamp with time zone类型相同。可选参数fractional_seconds_precision指定了秒域中小数部分的位数,范围0~9,默认值为6。nls_timestamp_tz_format指定了timestamp with time zone类型的显示格式。

红象数据库兼容Oracle数据类型介绍

timestamp with local time zone类型语法:

TIMESTAMP[(fractional_seconds_precision)] WITH LOCAL TIME ZONE

timestamp with local time zone是时区信息敏感的timestamp变种,它包含timestamp with time zone类型的所有值;timestamp with local time zone类型的数据在数据库中统一存储为UTC时间,时区信息不存储为列数据的一部分,当用户检索数据时,根据用户本地session的时区返回数据。可选参数fractional_seconds_precision指定了秒域中小数部分的位数,范围0~9,默认值为6。

由于底层使用PG现有的timestamp存储方式存储,受其存储方式的限制,秒域中小数部分的位数7到9位会显示0,且因PG的没有timestamp with local time zone类型,即timestamp with time zone没有存储时区,所以timestamp with local time zone与timestamp with time zone行为一致。

nls_timestamp_format指定了timestamp with local time zone类型的显示格式。

示例:

红象数据库兼容Oracle数据类型介绍

此外,Oracle的时间nls_date_format,nls_timestamp_format,nls_timestamp_tz_format的取值有可能在PG中不支持。这三个值可以设置为‘pg’,这是在输入时会尝试识别其格式(与PG行为一致)。

间隔类型

间隔类型包括interval year to month和interval day to second两种。可以指定year域、day域和小数秒的精度。

语法如下:

interval year(year_precision) to month

interval day(day_precision) to second(second_precision)

interval year to month类型使用日期时间的“年”和“月”域存储一段时间,这个数据类型用于体现只有年和月的值是有意义的两个日期时间值的差。可选参数year_precision是日期时间的年域的精度,有效范围是0 ~ 9,默认值为6。

示例:

红象数据库兼容Oracle数据类型介绍

interval day to second类型存储由日期时间的“天”、“小时”、“分钟”、“秒”域组成的一段时间,这个数据类型用于表示两个日期时间值的精确差。可选参数day_precision是日期时间day域的精度,有效范围是0~9,默认值为2;可选参数fractional_seconds_precision是日期时间秒域小数部分的数字位数,有效范围是0~9,默认值为6。

示例:

红象数据库兼容Oracle数据类型介绍

红象数据库兼容Oracle数据类型介绍

其他类型

Oracle的raw、long、blob、clob等数据类型目前实现为bytea或text的domain,未来计划实现对CLOB/BLOB类型兼容,但大对象的JDBC接口兼容了Oracle的用法。

在数据库的表中可以设置rowid,这时每一行都有一个唯一标识符oid,返回8字节,但实际占用4字节的存储空间,分别表示表的oid和行的oid。rowid是一个系统隐藏列,我们可以在创建表时通过with rowid来开启。同时支持rowid数据类型的隐藏列。

为什么不使用ctid作为rowid?主要是因为PG没有回滚段,不支持本地更新。

示例:

总结

红象数据库从类型系统开始实现与Oracle的数据类型的兼容,主要是不希望破坏原有PG的类型系统,从而能最大限度的利用PG的生态。为了实现简单和保证正确性,存储方面沿用了PG对应数据类型的存储,其他如类型的in/out、send/receive、精度的in/out、比较、操作符、显式/隐式转换等也参照了PG的实现。这些类型均在sys模式下,在Oracle兼容的模式下,如果名称相同(例如date),会优先查找到Oracle的date类型,如需访问PG的数据类型,需要在类型前增加pg_catalog模式的限定(例如pg_catalog.date)。