数据类型转换
Lakehouse 的类型转换分为显式转换和隐式转换两种。显式转换由用户通过
CAST 函数或 :: 符号指定;隐式转换由系统在算术运算、比较运算、函数调用等场景中自动完成。
显式转换
Lakehouse 支持两种显式类型转换语法,二者等价:
示例:
下表列出各类型之间转换的支持情况。
- 🟢 支持隐式转换(系统在运算或比较时自动执行,也可显式 CAST)
- 🔵 仅支持显式转换(必须用 CAST 或
指定):: - 🟠 仅支持显式转换,且可能因值越界在宽松模式下返回 NULL
- ✗ 不支持
| Source\Target | Tinyint | Smallint | Int | Bigint | Float | Double | Decimal | String | Date | Timestamp_ltz | Timestamp_ntz | Interval | Boolean | Binary | Array | Map | Struct | Vector | Bitmap |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Tinyint | 🟢 | 🟢 | 🟢 | 🟢 | 🔵 | 🟢 | 🟢 | 🟢 | ✗ | 🔵 | ✗ | ✗ | 🔵 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| Smallint | 🟠 | 🟢 | 🟢 | 🟢 | 🔵 | 🟢 | 🟢 | 🟢 | ✗ | 🔵 | ✗ | ✗ | 🔵 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| Int | 🟠 | 🟠 | 🟢 | 🟢 | 🔵 | 🟢 | 🟢 | 🟢 | ✗ | 🔵 | ✗ | ✗ | 🔵 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| Bigint | 🟠 | 🟠 | 🟠 | 🟢 | 🔵 | 🟢 | 🟢 | 🟢 | ✗ | 🔵 | ✗ | ✗ | 🔵 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| Float | 🟠 | 🟠 | 🟠 | 🟠 | 🟢 | 🟢 | 🟠 | 🟢 | ✗ | 🔵 | ✗ | ✗ | 🔵 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| Double | 🟠 | 🟠 | 🟠 | 🟠 | 🔵 | 🟢 | 🟠 | 🟢 | ✗ | 🔵 | ✗ | ✗ | 🔵 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| Decimal | 🟠 | 🟠 | 🟠 | 🟠 | 🔵 | 🟢 | 🟠 | 🟢 | ✗ | 🔵 | ✗ | ✗ | 🔵 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| String | 🟠 | 🟠 | 🟠 | 🟠 | 🟠 | 🟠 | 🟠 | 🟢 | 🟢 | 🟢 | 🟢 | 🟢 | 🟢 | 🟠 | ✗ | ✗ | ✗ | 🟠 | ✗ |
| Date | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | 🟢 | 🟢 | 🟢 | 🟢 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| Timestamp_ltz | 🟠 | 🟠 | 🟠 | 🟠 | 🟠 | 🟠 | 🟠 | 🟢 | 🔵 | 🟢 | 🔵 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| Timestamp_ntz | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | 🟢 | 🟢 | 🟢 | 🟢 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| Interval | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | 🟢 | ✗ | ✗ | ✗ | 🟢 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| Boolean | 🔵 | 🔵 | 🔵 | 🔵 | 🔵 | 🔵 | 🔵 | 🟢 | ✗ | ✗ | ✗ | ✗ | 🟢 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| Binary | ✗ | ✗ | 🔵 | 🔵 | ✗ | ✗ | ✗ | 🔵 | ✗ | ✗ | ✗ | ✗ | ✗ | 🟢 | ✗ | ✗ | ✗ | ✗ | ✗ |
| Array | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | 🔵 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | 🟠 | ✗ | ✗ | 🔵 | ✗ |
| Map | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | 🔵 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | 🟠 | ✗ | ✗ | ✗ |
| Struct | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | 🔵 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | 🟠 | ✗ | ✗ |
| Vector | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | 🔵 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | 🔵 | ✗ | ✗ | 🔵 | ✗ |
| Bitmap | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | 🔵 |
🟠 标注的转换在宽松模式下越界返回 NULL 而非报错。可通过
SET cz.sql.cast.mode=strict 开启严格模式,越界时直接报错;也可使用 TRY_CAST 函数,报错时返回 NULL。
-
数值类型越界(如
):宽松模式返回 NULL,严格模式报错CAST(18.234 AS DECIMAL(4,3)) -
FLOAT 转 INTEGER:截断小数部分(向零取整,如
,3.9 → 3
)-3.9 → -3 -
整数转 FLOAT:需显式 CAST;整数与 Float 混合运算时系统自动提升为 DOUBLE,不会停留在 Float
-
DOUBLE 转 FLOAT:需显式 CAST;超出 Float 范围时返回
/Infinity
,不返回 NULL(因此表格标 🔵 而非 🟠)-Infinity -
DECIMAL 转 FLOAT:需显式 CAST;超出 Float 精度范围时发生精度损失但不返回 NULL(因此表格标 🔵 而非 🟠)
-
String 转 Float/Double 支持
、'Infinity'
、'-Infinity'
等特殊值'NaN' -
FLOAT/DOUBLE 转 DECIMAL:需显式 CAST;小数位超出精度时截断(不返回 NULL),整数部分溢出时返回 NULL(如
→ NULL,因为 100.00 超出 99.99);表达式中 Float/Double 与 Decimal 混合运算结果为 DOUBLECAST(100.0F AS DECIMAL(4,2)) -
DECIMAL 转 DOUBLE:隐式支持(Decimal 在表达式中遇到浮点类型时自动提升为 DOUBLE)
-
数值转 BOOLEAN:0 为 false,非零(含负数)为 true
-
TIMESTAMP 转 DATE:丢弃时间部分(需显式 CAST)
-
所有数值类型转 Timestamp_ltz:数值被解释为 unix 时间戳(秒),需显式 CAST;Float/Double 转换时小数部分保留为毫秒;Float 精度有限,大时间戳转换后可能有秒级误差
-
Timestamp_ltz 转数值类型:提取 unix 时间戳(秒),需显式 CAST,可能越界返回 NULL(转 INT 时 2038 年后的时间戳超出 INT 范围,建议转 BIGINT)
-
Binary 转 Int/Bigint:需显式 CAST,按大端有符号字节序解释为整数(如
→X'FFFFFFFF'
,仅支持 32 位及以上整数类型)-1 -
Interval 同类转换(Interval → Interval):仅支持相同单位,不做单位换算(
结果仍为 1 天)CAST(INTERVAL '1' DAY AS INTERVAL HOUR) -
Array/Map/Struct 支持在同族类型内转换元素类型,需用尖括号语法指定目标元素类型;若元素值超出目标类型范围,该元素在宽松模式下返回 NULL(因此表格标 🟠);Struct 转 String 只输出字段值不含字段名(如
而非{1}
):{a:1} -
Vector 支持与 Array 互转(需指定元素类型:
、CAST(vec AS ARRAY<FLOAT>)
);Vector 元素类型固定为 FLOAT,不支持 DOUBLE;Vector 转 String 返回CAST(arr AS VECTOR(FLOAT, n))
格式的文本表示;Vector→Vector 转换要求维度一致,维度不匹配时报错[v1, v2, ...] -
Bitmap 不支持转换为其他类型,需使用专用函数:
(整数转 Bitmap)、to_bitmap()
(字符串转 Bitmap)、string_to_bitmap()
(Bitmap 转字符串)bitmap_to_string()
字面量写法
字面量是在 SQL 中直接表示某种类型值的语法,不经过 CAST 转换。
基本类型字面量
| 类型 | 字面量语法 | 示例 |
|---|---|---|
| TINYINT | 数字后加 | |
| SMALLINT | 数字后加 | |
| BIGINT | 数字后加 | |
| FLOAT | 数字后加 | |
| DOUBLE | 数字后加 | |
| DECIMAL | 数字后加 | |
| BOOLEAN | 直接写 | 、 |
| BINARY | | |
| DATE | | |
| TIMESTAMP | | |
| TIMESTAMP_NTZ | | |
| INTERVAL | | |
复杂类型构造函数
| 类型 | 构造语法 | 示例 |
|---|---|---|
| ARRAY | | |
| MAP | | |
| STRUCT | | |
| VECTOR | | |
INSERT 时的注意事项
INSERT 写入时,字符串不会隐式转换为 DATE/TIMESTAMP/TIMESTAMP_NTZ,必须使用字面量前缀或 CAST:
隐式转换
当两个不同类型的值进行算术运算、比较运算或 COALESCE/CASE/UNION 等操作时,Lakehouse 按类型优先级自动将低优先级类型提升为高优先级类型。
图中实线箭头表示隐式拓宽路径(低精度自动提升为高精度);虚线箭头表示该类型可隐式转换为 STRING。
主要规则:
- 整数链(精度由低到高):
TINYINT → SMALLINT → INT → BIGINT - 整数与
混合:当目标 DECIMAL 的整数位足以容纳整数类型时,整数提升为该 DECIMAL;否则隐式转换不成立DECIMAL - 任何整数或
与DECIMAL
/FLOAT
混合:结果统一提升为DOUBLE
(DOUBLE
在隐式提升中也会被升级为FLOAT
)DOUBLE
可隐式提升为DATE
或TIMESTAMP_LTZTIMESTAMP_NTZ
可隐式提升为TIMESTAMP_NTZ
;DATE 与两种 TIMESTAMP 混合时TIMESTAMP_LTZ
优先TIMESTAMP_LTZ
与其他类型混合时,STRING 被尝试转为该类型(含 INTEGER、DECIMAL、FLOAT/DOUBLE、DATE、TIMESTAMP、BOOLEAN、INTERVAL;转换失败则静默返回 NULL)STRING
可隐式转换为任意类型NULL
、ARRAY
、MAP
、STRUCT
、BINARY
、VECTOR
仅接受来自 NULL 的隐式转换BITMAP
场景示例:
算术运算——整数与 BIGINT 混合,自动提升为 BIGINT:
比较运算——DATE 与 TIMESTAMP 比较,DATE 自动提升为 TIMESTAMP_LTZ:
UNION ALL——TINYINT 与 INT 混合,结果列类型提升为 INT:
COALESCE——INT 与 DECIMAL 混合,结果提升为 DECIMAL:
Lakehouse 默认采用宽松模式:隐式转换失败时返回 NULL 而非报错。可通过
SET cz.sql.cast.mode=strict 开启严格模式。
类型转换注意事项
混合类型转换
宽松模式下,以下几种常见写法需要注意,混合类型转换失败时返回 NULL 而非报错:
UNION ALL 混合类型
字符串与数字混合时,系统按类型优先级尝试将字符串转为数值,无法转换的行变为 NULL:
推荐写法:显式统一类型
COALESCE 混合类型
COALESCE 按类型优先级推导公共类型,字符串参数可能被转为数值:
CASE 分支类型不一致
各分支返回值类型不同时,系统尝试转为公共类型,转换失败的分支返回 NULL:
推荐写法:
String 转数值类型
String 转 INT/BIGINT 时,仅接受纯整数格式:
String 转 BOOLEAN
String 转 BOOLEAN 时,仅识别特定的真值/假值字符串(前后空格自动忽略,不区分大小写):
| 输入 | 结果 | 说明 |
|---|---|---|
、、、、 | true | 真值(不区分大小写) |
、、、、 | false | 假值(不区分大小写) |
、、 等 | NULL | 其他值返回 NULL |
DECIMAL 越界行为
DECIMAL 转换时,若值超出目标精度范围,宽松模式下返回 NULL:
无效日期/时间
CAST 无效日期或时间时,返回 NULL 而非报错:
比较运算中的隐式转换
字符串与数值比较时,字符串会被尝试转为数值,转换失败返回 NULL:
Array 构造函数类型要求
ARRAY() 构造函数要求所有元素类型一致,混合类型会报错:
数值转 TIMESTAMP 的限制
数值类型只能转为 TIMESTAMP_LTZ(解释为 unix 时间戳),不支持直接转 TIMESTAMP_NTZ:
INTERVAL 字符串格式
INTERVAL 的 CAST 仅支持纯数字字符串:
示例
隐式转换:DECIMAL 与 DOUBLE 运算,结果提升为 DOUBLE:
显式转换:将字符串转换为 INT:
