SQL 数据类型规则
适用于: Databricks SQL Databricks Runtime
Azure Databricks 使用几个规则来解决数据类型之间的冲突:
还可以在多种类型之间显式强制转换:
- cast 函数在大多数类型之间进行强制转换,如果无法转换,则返回错误。
- try_cast 函数的工作方式类似于 cast 函数,但在传递无效值时返回 NULL。
- 其他内置函数使用提供的格式指令在不同类型之间强制转换。
类型提升
类型提升是将类型转换为同一类型系列的另一个类型的过程,其中包含原始类型的所有可能值。
因此,类型提升是一项安全操作。 例如,TINYINT
的范围为 -128
到 127
。 其所有可能值都可以安全地提升为 INTEGER
。
类型优先级列表
类型优先级列表定义给定数据类型的值是否可以隐式提升为另一种数据类型。
数据类型 | 优先级列表(从低到高) |
---|---|
TINYINT | TINYINT -> SMALLINT -> INT -> BIGINT -> DECIMAL -> FLOAT (1) -> DOUBLE |
SMALLINT | SMALLINT -> INT -> BIGINT -> DECIMAL -> FLOAT > -> DOUBLE |
INT | INT -> BIGINT -> DECIMAL -> FLOAT > -> DOUBLE |
BIGINT | BIGINT -> DECIMAL -> FLOAT > -> DOUBLE |
DECIMAL | DECIMAL -> FLOAT > -> DOUBLE |
FLOAT | FLOAT (1) -> DOUBLE |
DOUBLE | DOUBLE |
DATE | DATE -> TIMESTAMP |
TIMESTAMP | TIMESTAMP |
ARRAY | ARRAY (2) |
BINARY | BINARY |
BOOLEAN | BOOLEAN |
INTERVAL | INTERVAL |
MAP | MAP (2) |
STRING | STRING |
STRUCT | STRUCT (2) |
VARIANT | VARIANT |
OBJECT | OBJECT (3) |
(1) 对于最不常见的类型解析,会跳过 FLOAT
以避免精度损失。
(2) 对于复杂类型,优先级规则以递归顺序应用于其组件元素。
(3) OBJECT
仅存在于 VARIANT
中。
字符串和 NULL
特殊规则适用于 STRING
和未键入 NULL
:
NULL
NULL 可以提升为任何其他类型。STRING
可以提升为BIGINT
、BINARY
、BOOLEAN
、DATE
、DOUBLE
、INTERVAL
和TIMESTAMP
。 如果无法将实际字符串值强制转换为最不常见类型,Azure Databricks 会引发运行时错误。 提升为INTERVAL
时,字符串值必须与间隔单位匹配。
类型优先级图
这是优先级层次结构的图形描述,结合了类型优先级列表和字符串和 NULL 规则。
最不常见的类型解析
一组类型中最不常见的类型是在由该类型组的所有元素构成的类型优先级图中可达到的最窄类型。
最不常见的类型解析用于:
- 确定是否可以使用较窄类型的实参调用需要给定类型的形参的函数。
- 为需要多个形参的共享实参类型的函数(例如 coalesce、in、least 或 greatest)派生实参类型。
- 派生运算符(如算术运算符或比较运算符)的操作数类型。
- 派生表达式(如 case 表达式)的结果类型。
- 派生数组和映射构造函数的元素、键或值类型。
- 派生 UNION、INTERSECT 或 EXCEPT 集运算符的结果类型。
如果最不常见的类型解析为 FLOAT
,则应用特殊规则。 如果任何参与类型为精确的数值类型(TINYINT
、SMALLINT
、INTEGER
、BIGINT
或 DECIMAL
),则推出的最不常见类型均为 DOUBLE
,以避免可能的数字丢失。
隐式向下转换和交叉转换
Azure Databricks 仅在函数和运算符调用上使用这些形式的隐式强制转换,并且仅可明确确定意图。
隐式向下转换
隐式向下转换会自动将较宽类型强制转换到较窄类型,而无需显式指定强制转换。 向下转换很方便,但如果实际值在窄类型中无法表示,则存在意外运行时错误的风险。
向下转换按逆序应用类型优先级列表。
隐式交叉转换
隐式交叉转换将值从一个类型系列强制转换到另一个类型系列,而无需显式指定强制转换。
Azure Databricks 支持从以下位置进行隐式交叉转换:
- 到
STRING
的任何简单类型(BINARY
除外)。 STRING
到任何简单类型。
- 到
函数调用上的强制转换
给定解析的函数或运算符后,以下规则按其列出顺序应用于每个参数和参数对:
如果受支持的参数类型是参数类型优先级关系图的一部分,Azure Databricks 会将参数提升为该参数类型。
在大多数情况下,函数说明显式声明支持的类型或链,例如“任何数值类型”。
例如,sin(expr) 在
DOUBLE
上运算,但将接受任何数值。如果所需的参数类型为
STRING
,并且参数类型为简单类型,则 Azure Databricks 会将参数交叉转换为字符串参数类型。例如,substr(str, start, len) 需要
str
为STRING
。 相反,可以传递数字或日期/时间类型。如果参数类型为
STRING
,并且所需的参数类型为简单类型,则 Azure Databricks 会将字符串参数交叉转换为最宽受支持参数类型。例如,date_add(date, days) 需要
DATE
和INTEGER
。如果调用
date_add()
时使用了两个STRING
,则 Azure Databricks 会将第一个STRING
交叉转换 为DATE
,将第二个STRING
交叉转换为INTEGER
。如果函数需要数值类型(例如
INTEGER
)或DATE
类型,但参数是更通用的类型(如DOUBLE
或TIMESTAMP
),Azure Databricks 会将参数隐式向下转换为该参数类型。例如,date_add(date, days) 需要
DATE
和INTEGER
。如果调用
date_add()
时使用了TIMESTAMP
和BIGINT
,则 Azure Databricks 会通过删除时间组件将TIMESTAMP
向下转换为DATE
,将BIGINT
向下转换为INTEGER
。否则,Azure Databricks 会引发错误。
示例
coalesce 函数接受任何一组实参类型,但前提是它们共有一个最不常见类型。
结果类型是实参中的最不常见类型。
-- The least common type of TINYINT and BIGINT is BIGINT
> SELECT typeof(coalesce(1Y, 1L, NULL));
BIGINT
-- INTEGER and DATE do not share a precedence chain or support crosscasting in either direction.
> SELECT typeof(coalesce(1, DATE'2020-01-01'));
Error: Incompatible types [INT, DATE]
-- Both are ARRAYs and the elements have a least common type
> SELECT typeof(coalesce(ARRAY(1Y), ARRAY(1L)))
ARRAY<BIGINT>
-- The least common type of INT and FLOAT is DOUBLE
> SELECT typeof(coalesce(1, 1F))
DOUBLE
> SELECT typeof(coalesce(1L, 1F))
DOUBLE
> SELECT typeof(coalesce(1BD, 1F))
DOUBLE
-- The least common type between an INT and STRING is BIGINT
> SELECT typeof(coalesce(5, '6'));
BIGINT
-- The least common type is a BIGINT, but the value is not BIGINT.
> SELECT coalesce('6.1', 5);
Error: 6.1 is not a BIGINT
-- The least common type between a DECIMAL and a STRING is a DOUBLE
> SELECT typeof(coalesce(1BD, '6'));
DOUBLE
substring 函数需要 STRING
类型的字符串参数和 INTEGER
作为开头和长度参数。
-- Promotion of TINYINT to INTEGER
> SELECT substring('hello', 1Y, 2);
he
-- No casting
> SELECT substring('hello', 1, 2);
he
-- Casting of a literal string
> SELECT substring('hello', '1', 2);
he
-- Downcasting of a BIGINT to an INT
> SELECT substring('hello', 1L, 2);
he
-- Crosscasting from STRING to INTEGER
> SELECT substring('hello', str, 2)
FROM VALUES(CAST('1' AS STRING)) AS T(str);
he
-- Crosscasting from INTEGER to STRING
> SELECT substring(12345, 2, 2);
23
|| (CONCAT) 允许隐式交叉转换到字符串。
-- A numeric is cast to STRING
> SELECT 'This is a numeric: ' || 5.4E10;
This is a numeric: 5.4E10
-- A date is cast to STRING
> SELECT 'This is a date: ' || DATE'2021-11-30';
This is a date: 2021-11-30
由于隐式向下转换,date_add 可以使用 TIMESTAMP
或 BIGINT
调用。
> SELECT date_add(TIMESTAMP'2011-11-30 08:30:00', 5L);
2011-12-05
由于隐式向下转换,date_add 可以使用 STRING
调用。
> SELECT date_add('2011-11-30 08:30:00', '5');
2011-12-05