数据类型转换

Lakehouse 的类型转换分为显式转换和隐式转换两种。显式转换由用户通过

CAST
CAST
函数或
::
::
符号指定;隐式转换由系统在算术运算、比较运算、函数调用等场景中自动完成。

显式转换

Lakehouse 支持两种显式类型转换语法,二者等价:

CAST(a AS INT) a::INT

示例:

SELECT '123'::INT, '3.14'::DOUBLE, '2024-01-15'::DATE; -- 返回:123 | 3.14 | 2024-01-15

下表列出各类型之间转换的支持情况。

  • 🟢 支持隐式转换(系统在运算或比较时自动执行,也可显式 CAST)
  • 🔵 仅支持显式转换(必须用 CAST 或
    ::
    ::
    指定)
  • 🟠 仅支持显式转换,且可能因值越界在宽松模式下返回 NULL
  • ✗ 不支持
Source\TargetTinyintSmallintIntBigintFloatDoubleDecimalStringDateTimestamp_ltzTimestamp_ntzIntervalBooleanBinaryArrayMapStructVectorBitmap
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
SET cz.sql.cast.mode=strict
开启严格模式,越界时直接报错;也可使用
TRY_CAST
TRY_CAST
函数,报错时返回 NULL。

  • 数值类型越界(如

    CAST(18.234 AS DECIMAL(4,3))
    CAST(18.234 AS DECIMAL(4,3))
    ):宽松模式返回 NULL,严格模式报错

  • FLOAT 转 INTEGER:截断小数部分(向零取整,如

    3.9 → 3
    3.9 → 3
    -3.9 → -3
    -3.9 → -3

  • 整数转 FLOAT:需显式 CAST;整数与 Float 混合运算时系统自动提升为 DOUBLE,不会停留在 Float

  • DOUBLE 转 FLOAT:需显式 CAST;超出 Float 范围时返回

    Infinity
    Infinity
    /
    -Infinity
    -Infinity
    ,不返回 NULL(因此表格标 🔵 而非 🟠)

  • DECIMAL 转 FLOAT:需显式 CAST;超出 Float 精度范围时发生精度损失但不返回 NULL(因此表格标 🔵 而非 🟠)

  • String 转 Float/Double 支持

    'Infinity'
    'Infinity'
    '-Infinity'
    '-Infinity'
    'NaN'
    'NaN'
    等特殊值

  • FLOAT/DOUBLE 转 DECIMAL:需显式 CAST;小数位超出精度时截断(不返回 NULL),整数部分溢出时返回 NULL(如

    CAST(100.0F AS DECIMAL(4,2))
    CAST(100.0F AS DECIMAL(4,2))
    → NULL,因为 100.00 超出 99.99);表达式中 Float/Double 与 Decimal 混合运算结果为 DOUBLE

  • 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'
    X'FFFFFFFF'
    -1
    -1
    ,仅支持 32 位及以上整数类型)

  • Interval 同类转换(Interval → Interval):仅支持相同单位,不做单位换算(

    CAST(INTERVAL '1' DAY AS INTERVAL HOUR)
    CAST(INTERVAL '1' DAY AS INTERVAL HOUR)
    结果仍为 1 天)

  • Array/Map/Struct 支持在同族类型内转换元素类型,需用尖括号语法指定目标元素类型;若元素值超出目标类型范围,该元素在宽松模式下返回 NULL(因此表格标 🟠);Struct 转 String 只输出字段值不含字段名(如

    {1}
    {1}
    而非
    {a:1}
    {a:1}
    ):

    SELECT CAST(ARRAY(1, 2, 3) AS ARRAY<BIGINT>); SELECT CAST(MAP('a', 1) AS MAP<STRING, BIGINT>); SELECT CAST(named_struct('a', 1) AS STRUCT<a:BIGINT>); -- 元素越界示例: SELECT CAST(ARRAY(999999999999L, 2L) AS ARRAY<TINYINT>); -- [NULL, 2]

  • Vector 支持与 Array 互转(需指定元素类型:

    CAST(vec AS ARRAY<FLOAT>)
    CAST(vec AS ARRAY<FLOAT>)
    CAST(arr AS VECTOR(FLOAT, n))
    CAST(arr AS VECTOR(FLOAT, n))
    );Vector 元素类型固定为 FLOAT,不支持 DOUBLE;Vector 转 String 返回
    [v1, v2, ...]
    [v1, v2, ...]
    格式的文本表示;Vector→Vector 转换要求维度一致,维度不匹配时报错

  • Bitmap 不支持转换为其他类型,需使用专用函数:

    to_bitmap()
    to_bitmap()
    (整数转 Bitmap)、
    string_to_bitmap()
    string_to_bitmap()
    (字符串转 Bitmap)、
    bitmap_to_string()
    bitmap_to_string()
    (Bitmap 转字符串)

字面量写法

字面量是在 SQL 中直接表示某种类型值的语法,不经过 CAST 转换。

基本类型字面量

类型字面量语法示例
TINYINT数字后加
Y
Y
1Y
1Y
SMALLINT数字后加
S
S
100S
100S
BIGINT数字后加
L
L
9999999999L
9999999999L
FLOAT数字后加
F
F
3.14F
3.14F
DOUBLE数字后加
D
D
3.14D
3.14D
DECIMAL数字后加
BD
BD
3.14BD
3.14BD
BOOLEAN直接写
true
true
false
false
BINARY
X'十六进制'
X'十六进制'
X'41424344'
X'41424344'
DATE
DATE'yyyy-MM-dd'
DATE'yyyy-MM-dd'
DATE'2024-01-15'
DATE'2024-01-15'
TIMESTAMP
TIMESTAMP'yyyy-MM-dd HH:mm:ss'
TIMESTAMP'yyyy-MM-dd HH:mm:ss'
TIMESTAMP'2024-01-15 08:30:00'
TIMESTAMP'2024-01-15 08:30:00'
TIMESTAMP_NTZ
TIMESTAMP_NTZ'yyyy-MM-dd HH:mm:ss'
TIMESTAMP_NTZ'yyyy-MM-dd HH:mm:ss'
TIMESTAMP_NTZ'2024-01-15 08:30:00'
TIMESTAMP_NTZ'2024-01-15 08:30:00'
INTERVAL
INTERVAL '值' 单位
INTERVAL '值' 单位
INTERVAL '3' DAY
INTERVAL '3' DAY

复杂类型构造函数

类型构造语法示例
ARRAY
ARRAY(v1, v2, ...)
ARRAY(v1, v2, ...)
ARRAY(1, 2, 3)
ARRAY(1, 2, 3)
MAP
MAP(k1, v1, k2, v2, ...)
MAP(k1, v1, k2, v2, ...)
MAP('a', 1, 'b', 2)
MAP('a', 1, 'b', 2)
STRUCT
named_struct('字段名', 值, ...)
named_struct('字段名', 值, ...)
named_struct('id', 1, 'name', 'Alice')
named_struct('id', 1, 'name', 'Alice')
VECTOR
vector(v1, v2, ...)
vector(v1, v2, ...)
vector(1.0, 2.0, 3.0)
vector(1.0, 2.0, 3.0)

INSERT 时的注意事项

INSERT 写入时,字符串不会隐式转换为 DATE/TIMESTAMP/TIMESTAMP_NTZ,必须使用字面量前缀或 CAST:

-- 报错:string 不能隐式转为 date INSERT INTO t VALUES ('2024-01-15'); -- 正确写法一:字面量前缀 INSERT INTO t VALUES (DATE'2024-01-15'); -- 正确写法二:CAST INSERT INTO t VALUES (CAST('2024-01-15' AS DATE));

隐式转换

当两个不同类型的值进行算术运算、比较运算或 COALESCE/CASE/UNION 等操作时,Lakehouse 按类型优先级自动将低优先级类型提升为高优先级类型。

图中实线箭头表示隐式拓宽路径(低精度自动提升为高精度);虚线箭头表示该类型可隐式转换为 STRING。

主要规则:

  • 整数链(精度由低到高):
    TINYINT → SMALLINT → INT → BIGINT
    TINYINT → SMALLINT → INT → BIGINT
  • 整数与
    DECIMAL
    DECIMAL
    混合:当目标 DECIMAL 的整数位足以容纳整数类型时,整数提升为该 DECIMAL;否则隐式转换不成立
  • 任何整数或
    DECIMAL
    DECIMAL
    FLOAT
    FLOAT
    /
    DOUBLE
    DOUBLE
    混合:结果统一提升为
    DOUBLE
    DOUBLE
    FLOAT
    FLOAT
    在隐式提升中也会被升级为
    DOUBLE
    DOUBLE
  • DATE
    DATE
    可隐式提升为
    TIMESTAMP_LTZ
    TIMESTAMP_LTZ
    TIMESTAMP_NTZ
    TIMESTAMP_NTZ
  • TIMESTAMP_NTZ
    TIMESTAMP_NTZ
    可隐式提升为
    TIMESTAMP_LTZ
    TIMESTAMP_LTZ
    ;DATE 与两种 TIMESTAMP 混合时
    TIMESTAMP_LTZ
    TIMESTAMP_LTZ
    优先
  • STRING
    STRING
    与其他类型混合时,STRING 被尝试转为该类型(含 INTEGER、DECIMAL、FLOAT/DOUBLE、DATE、TIMESTAMP、BOOLEAN、INTERVAL;转换失败则静默返回 NULL)
  • NULL
    NULL
    可隐式转换为任意类型
  • ARRAY
    ARRAY
    MAP
    MAP
    STRUCT
    STRUCT
    BINARY
    BINARY
    VECTOR
    VECTOR
    BITMAP
    BITMAP
    仅接受来自 NULL 的隐式转换

场景示例:

算术运算——整数与 BIGINT 混合,自动提升为 BIGINT:

SELECT typeof(100 + 9999999999L); -- 返回:bigint

比较运算——DATE 与 TIMESTAMP 比较,DATE 自动提升为 TIMESTAMP_LTZ:

SELECT CAST('2024-01-15' AS DATE) < TIMESTAMP '2024-01-15 12:00:00'; -- 返回:true

UNION ALL——TINYINT 与 INT 混合,结果列类型提升为 INT:

SELECT typeof(a) FROM ( SELECT 1Y AS a UNION ALL SELECT 1000 ) t; -- 返回:int

COALESCE——INT 与 DECIMAL 混合,结果提升为 DECIMAL:

SELECT typeof(COALESCE(1, 3.14BD)); -- 返回:decimal(12,2)

Lakehouse 默认采用宽松模式:隐式转换失败时返回 NULL 而非报错。可通过

SET cz.sql.cast.mode=strict
SET cz.sql.cast.mode=strict
开启严格模式。

类型转换注意事项

混合类型转换

宽松模式下,以下几种常见写法需要注意,混合类型转换失败时返回 NULL 而非报错:

UNION ALL 混合类型

字符串与数字混合时,系统按类型优先级尝试将字符串转为数值,无法转换的行变为 NULL:

SELECT 'abc' UNION ALL SELECT 123; -- 结果:NULL, 123('abc' 无法转为数值,静默变 NULL)

推荐写法:显式统一类型

SELECT CAST('abc' AS STRING) UNION ALL SELECT CAST(123 AS STRING); -- 结果:'abc', '123'

COALESCE 混合类型

COALESCE
COALESCE
按类型优先级推导公共类型,字符串参数可能被转为数值:

SELECT COALESCE('abc', 123); -- 结果:123('abc' 转数值失败变 NULL,跳过,返回 123) SELECT COALESCE(NULL, 'abc', 123); -- 结果:123(同上,'abc' 被转为数值失败变 NULL)

CASE 分支类型不一致

各分支返回值类型不同时,系统尝试转为公共类型,转换失败的分支返回 NULL:

SELECT CASE WHEN 1=1 THEN 'abc' ELSE 123 END; -- 结果:NULL('abc' 无法转为数值,该分支变 NULL)

推荐写法:

SELECT CASE WHEN 1=1 THEN 'abc' ELSE CAST(123 AS STRING) END; -- 结果:'abc'

String 转数值类型

String 转 INT/BIGINT 时,仅接受纯整数格式:

SELECT CAST('123' AS INT); -- 123(正常) SELECT CAST(' 123 ' AS INT); -- 123(前后空格自动忽略) SELECT CAST('00123' AS INT); -- 123(前导零自动忽略) SELECT CAST('1.0' AS INT); -- NULL(含小数点,不支持) SELECT CAST('1e10' AS INT); -- NULL(科学计数法,不支持) SELECT CAST('+123' AS INT); -- NULL(正号,不支持;但 '-123' 正常) SELECT CAST('' AS INT); -- NULL(空字符串)

String 转 BOOLEAN

String 转 BOOLEAN 时,仅识别特定的真值/假值字符串(前后空格自动忽略,不区分大小写):

输入结果说明
'true'
'true'
't'
't'
'yes'
'yes'
'y'
'y'
'1'
'1'
true真值(不区分大小写)
'false'
'false'
'f'
'f'
'no'
'no'
'n'
'n'
'0'
'0'
false假值(不区分大小写)
'2'
'2'
'abc'
'abc'
''
''
NULL其他值返回 NULL

DECIMAL 越界行为

DECIMAL 转换时,若值超出目标精度范围,宽松模式下返回 NULL:

SELECT CAST(18.234 AS DECIMAL(4,3)); -- NULL(最大值 9.999,18.234 越界) SELECT CAST(9.999 AS DECIMAL(3,2)); -- NULL(四舍五入后 10.00 超出范围) SELECT CAST(9.995 AS DECIMAL(4,2)); -- 10.00(半值进位)

无效日期/时间

CAST 无效日期或时间时,返回 NULL 而非报错:

SELECT CAST('2024-02-30' AS DATE); -- NULL(2 月无 30 日) SELECT CAST('2024-01-15 25:00:00' AS TIMESTAMP); -- NULL(小时超出范围)

比较运算中的隐式转换

字符串与数值比较时,字符串会被尝试转为数值,转换失败返回 NULL:

SELECT '123' = 123; -- true('123' 成功转为 123) SELECT 'abc' > 123; -- NULL('abc' 无法转为数值) SELECT '+123' = 123; -- NULL(正号不支持)

Array 构造函数类型要求

ARRAY()
ARRAY()
构造函数要求所有元素类型一致,混合类型会报错:

SELECT ARRAY(1, 2, 3); -- 正常:array<int> SELECT ARRAY(1, 'a', true); -- 报错:inputs to function array() should be the same type

数值转 TIMESTAMP 的限制

数值类型只能转为 TIMESTAMP_LTZ(解释为 unix 时间戳),不支持直接转 TIMESTAMP_NTZ:

SELECT CAST(1705278600 AS TIMESTAMP); -- 2024-01-15 08:30:00(TIMESTAMP_LTZ,本地时区) SELECT CAST(1705278600 AS TIMESTAMP_NTZ); -- 报错 SELECT CAST(3.14F AS TIMESTAMP); -- 1970-01-01 08:00:03.140(小数部分为毫秒)

INTERVAL 字符串格式

INTERVAL 的 CAST 仅支持纯数字字符串:

SELECT CAST('3' AS INTERVAL DAY); -- 3 天(正常) SELECT CAST('3 days' AS INTERVAL DAY); -- NULL(不支持文本单位) SELECT CAST(86400 AS INTERVAL DAY); -- 报错(不支持整数直接转)

示例

隐式转换:DECIMAL 与 DOUBLE 运算,结果提升为 DOUBLE:

SELECT typeof(10BD + 3.14D); -- 返回:double

显式转换:将字符串转换为 INT:

SELECT CAST('123' AS INT); -- 返回:123

联系我们
预约咨询
微信咨询
电话咨询
邮件咨询