传统数据库中表的字段有多种数据类型,Flink SQL API 也为表(动态表)中的字段提供了丰富的数据类型。在Flink sql中decimal类型和varchar类型是常用的两种数据类型。整理近期使用过程中的几点总结如下。
一、decimal类型
decimal数据类型的标准写法为 DECIMAL(p,s)。p 是数字的位数(精度),s 是数字中小数点右边的位数(尾数)。
1=< p <=38,p的默认值为10。
0=< s <= p,s的默认值 为 0。
即一个数据如果被定义为 decimal,则等价于decimal(10,0)。
在日常开发中,曾遇到将一个字符串类型数据转换为decimal类型的场景。初版的sql写法如下。
cast(a as decimal) as a
在后期验数过程中发现a的原始数值 带多个小数位例如2.3894。经过上述转换则小数位被舍弃,只保留了整数位。而这种失真的处理并不符合期望。故修改后的sql如下。
cast(a as decimal(16,2)) as a
二、varchar类型
varchar类型即为可变长字符串,和Java中的String类型的功能一致。
varchar类型进行大小比较时默认是比较是按字典顺序比较它们的字符。
例如 字段a为varchar类型,代表用户id。则筛选用户id大于10的sql为
a > '10'
这时每条数据均和字符串‘10’按照Unicode值进行逐个字符的比较。
当然都转化为int类型再进行比较也是相同的结果。
cast(a as int ) > 10
值得注意的是很多场景中会将时间属性的字段设置为varchar类型。
比如字段b代表交易日期,varchar类型,格式为'2024-05-07'。字段c代表交易时间,varchar类型,格式为 '10:20:15'。则筛选交易日期大于'2024-03-01'且交易时间在'15:00:00'以后的sql如下。
where b > '2024-03-01' and c > '15:00:00'
根据上述sql,数据在进行比较时并不是按照日期和时间类型进行比较,而是比较将数据的字符unicode码值和'2024-03-01'及'15:00:00'分别进行比较。
在日期格式为'yyyy-MM-dd'和时间格式为'HH:mm:ss'的前提下,上述varchar类型的比较格式是合理的。效果和转换为日期/时间格式后再比较是一致的。
但是如果日期/时间字段非标准格式,则会产生错误的结果。
场景1:日期类型'dd-MM-yyyy'。比如字符串“01-02-2023”(代表 2023 年 2 月 1 日)将被视为大于字符串“12-01-2024”(代表 2024 年 1 月 12 日),即使后者日期更晚。
场景2:时间字段取值不固定。'2024-03-01 00:00:00' > '2024-03-01'是成立的,即使在业务含义两者一致。
故代表时间含义的字段尽量转换为时间/日期的格式再进行比较。若以varchar类型进行比较则注意要符合标准格式。
附上ASCII码值表(Unicode码值表的子集)以理解上述对比。
三、参考