⌘+k ctrl+k
1.3 (稳定版)
搜索快捷键 cmd + k | ctrl + k
类型转换

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

显式转换

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

隐式转换

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

隐式转换只能针对某些类型组合添加,并且通常只有当转换不会失败时才可能。例如,可以从 INTEGERDOUBLE 添加隐式转换,但不能从 DOUBLEINTEGER

考虑函数 sin(DOUBLE)。此函数接受 DOUBLE 类型的列作为输入参数,然而,它也可以用整数调用:sin(1)。该整数在传递给 sin 函数之前会转换为双精度浮点数。

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

组合转换

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

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

转换操作矩阵

特定数据类型的值并非总是可以转换为任意目标数据类型。唯一的例外是 NULL 值,它总是可以在类型之间进行转换。以下矩阵描述了支持哪些转换。当允许隐式转换时,这意味着显式转换也是可能的。

Typecasting matrix

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

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

有损转换

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

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

溢出

会导致值溢出的转换操作将抛出错误。例如,值 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')具有特殊的隐式转换规则。更多信息请参阅 常量类型页面

列表 / 数组

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

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

数组

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

结构体

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

此要求背后的理由是帮助避免意外错误。如果两个结构体没有共同的字段,则此转换可能并非预期。

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}];

联合体

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