⌘+k ctrl+k
1.4 (LTS)
搜索快捷键 cmd + k | ctrl + k
类型转换

类型转换是一种将特定数据类型的值转换为另一种数据类型中最接近的对应值的操作。与其他 SQL 引擎一样,DuckDB 同时支持隐式类型转换和显式类型转换。

显式转换 (Explicit Casting)

显式类型转换通过使用 CAST 表达式来执行。例如,CAST(col AS VARCHAR)col::VARCHAR 会将列 col 显式转换为 VARCHAR。有关更多信息,请参阅 cast 页面

隐式转换 (Implicit Casting)

在许多情况下,系统会自动添加转换。这被称为隐式转换。例如,当函数被调用时,传入的参数类型与函数要求的类型不匹配,但可以转换为所需类型时,就会发生这种情况。

隐式转换仅适用于部分类型组合,且通常仅在转换不会失败的情况下才可能发生。例如,可以从 INTEGER 隐式转换为 DOUBLE,但不能从 DOUBLE 隐式转换为 INTEGER

考虑函数 sin(DOUBLE)。该函数接收 DOUBLE 类型的列作为输入参数,但也可以使用整数进行调用:sin(1)。在传递给 sin 函数之前,该整数会被转换为 double 类型。

提示:要检查某种类型是否可以隐式转换为另一种类型,请使用 can_cast_implicitly 函数

组合转换 (Combination Casting)

当不同类型的值需要组合成一个未指定的共同父类型时,系统会执行隐式转换,自动选择一个父类型。例如,list_value(1::INT64, 1::UINT64) 会创建一个 INT128[] 类型的列表。在这种情况下执行的隐式转换有时比常规的隐式转换更宽松。例如,BOOL 值可以被转换为 INTtrue 映射为 1false 映射为 0),尽管这在常规隐式转换中是不可能的。

这种组合转换发生在比较运算 (= / < / >)、集合运算 (UNION / EXCEPT / INTERSECT) 以及嵌套类型构造函数 (list_value / [...] / MAP) 中。

转换操作矩阵

特定数据类型的值并不总是可以转换为任何任意目标数据类型。唯一的例外是 NULL 值——它总是可以在各种类型之间转换。下表描述了支持哪些转换。当允许隐式转换时,意味着也允许显式转换。

Typecasting matrix

即使基于源数据类型和目标数据类型支持某种转换操作,也不一定意味着该转换操作在运行时一定会成功。

已弃用:在 0.10.0 版本之前,DuckDB 允许在函数绑定期间将任何类型隐式转换为 VARCHAR。0.10.0 版本引入了一项破坏性更改,不再允许隐式转换为 VARCHAR。可以使用 old_implicit_casting 配置选项设置来恢复旧行为。但是,请注意此标志将在未来被弃用。

有损转换 (Lossy Casts)

允许执行导致精度损失的转换操作。例如,可以将带有小数部分的数值类型(如 DECIMALFLOATDOUBLE)显式转换为整数类型(如 INTEGERBIGINT)。数值会被四舍五入。

SELECT CAST(3.1 AS INTEGER);  -- 3
SELECT CAST(3.5 AS INTEGER);  -- 4
SELECT CAST(-1.7 AS INTEGER); -- -2

溢出 (Overflows)

会导致值溢出的转换操作会抛出错误。例如,值 999 对于 TINYINT 数据类型来说太大。因此,尝试将该值转换为该类型会导致运行时错误。

SELECT CAST(999 AS TINYINT);
Conversion Error:
Type INT32 with value 999 can't be cast because the value is out of range for the destination type INT8

因此,即使支持从 INTEGERTINYINT 的转换操作,该特定值也是无法转换的。TRY_CAST 可用于将值转换为 NULL,而不是抛出错误。

Varchar

VARCHAR 类型充当通用目标:任何任意类型的值总是可以转换为 VARCHAR 类型。此类型也用于在 shell 中显示值。

SELECT CAST(42.5 AS VARCHAR);

支持从 VARCHAR 转换为其他数据类型,但如果 DuckDB 无法解析并将提供的文本转换为目标数据类型,则可能会在运行时引发错误。

SELECT CAST('NotANumber' AS INTEGER);

通常,转换为 VARCHAR 是一种无损操作,任何类型在转换为文本后都可以转换回原始类型。

SELECT CAST(CAST([1, 2, 3] AS VARCHAR) AS INTEGER[]);

字面量类型

整数常量(如 42)和字符串常量(如 'string')具有特殊的隐式转换规则。有关更多信息,请参阅 常量类型页面

列表 / 数组 (Lists / Arrays)

列表可以使用相同的转换规则显式转换为其他列表。转换应用于列表的子元素。例如,如果我们转换一个 INTEGER[] 列表到一个 VARCHAR[] 列表,其中的 INTEGER 子元素会被逐个转换为 VARCHAR 并构建成一个新的列表。

SELECT CAST([1, 2, 3] AS VARCHAR[]);

数组 (Arrays)

数组遵循与列表相同的转换规则。此外,数组可以隐式转换为相同类型的列表。例如,INTEGER[3] 数组可以隐式转换为 INTEGER[] 列表。

结构体 (Structs)

只要结构体至少共享一个字段,就可以将它们转换为其他结构体。

此要求的初衷是为了避免意外错误。如果两个结构体没有任何共同字段,那么该转换很可能并非预期的。

SELECT CAST({'a': 42} AS STRUCT(a VARCHAR));

目标结构体中存在但源结构体中不存在的字段,默认设为 NULL

SELECT CAST({'a': 42} AS STRUCT(a VARCHAR, b VARCHAR));

仅存在于源结构体中的字段将被忽略。

SELECT CAST({'a': 42, 'b': 43} AS STRUCT(a VARCHAR));

结构体的名称顺序也可以不同。结构体的字段将根据其名称进行重新排列。

SELECT CAST({'a': 42, 'b': 84} AS STRUCT(b VARCHAR, a VARCHAR));

对于组合转换,结果结构体的字段是所有输入结构体字段的并集。此逻辑也递归地适用于潜在的嵌套结构体。

SELECT {'outer1': {'inner1': 42, 'inner2': 42}} AS c
UNION
SELECT {'outer1': {'inner2': 'hello', 'inner3': 'world'}, 'outer2': '100'} AS c;
SELECT [{'a': 42}, {'b': 84}];

联合体 (Unions)

联合体的转换规则可以在 UNION 类型页面 上找到。

© 2025 DuckDB 基金会,阿姆斯特丹,荷兰
行为准则 商标使用指南