- 安装
- 文档
- 入门
- 连接
- 数据导入
- 客户端 API
- 概览
- ADBC
- C
- C++
- CLI
- Dart
- Go
- Java (JDBC)
- Julia
- Node.js (已弃用)
- Node.js (Neo)
- ODBC
- PHP
- Python
- R
- Rust
- Swift
- Wasm
- SQL
- 介绍
- 语句
- 概览
- ANALYZE
- ALTER TABLE
- ALTER VIEW
- ATTACH 和 DETACH
- CALL
- CHECKPOINT
- COMMENT ON
- COPY
- CREATE INDEX
- CREATE MACRO
- CREATE SCHEMA
- CREATE SECRET
- CREATE SEQUENCE
- CREATE TABLE
- CREATE VIEW
- CREATE TYPE
- DELETE
- DESCRIBE
- DROP
- EXPORT 和 IMPORT DATABASE
- INSERT
- LOAD / INSTALL
- PIVOT
- 性能分析
- SELECT
- SET / RESET
- SET VARIABLE
- SUMMARIZE
- 事务管理
- UNPIVOT
- UPDATE
- USE
- VACUUM
- 查询语法
- SELECT
- FROM 和 JOIN
- WHERE
- GROUP BY
- GROUPING SETS
- HAVING
- ORDER BY
- LIMIT 和 OFFSET
- SAMPLE
- 展开嵌套
- WITH
- WINDOW
- QUALIFY
- VALUES
- FILTER
- 集合操作
- 预处理语句
- 数据类型
- 表达式
- 函数
- 概览
- 聚合函数
- 数组函数
- 位字符串函数
- Blob 函数
- 日期格式化函数
- 日期函数
- 日期部分函数
- 枚举函数
- 间隔函数
- Lambda 函数
- 列表函数
- 映射函数
- 嵌套函数
- 数值函数
- 模式匹配
- 正则表达式
- 结构体函数
- 文本函数
- 时间函数
- 时间戳函数
- 带时区时间戳函数
- 联合函数
- 实用函数
- 窗口函数
- 约束
- 索引
- 元查询
- DuckDB 的 SQL 方言
- 示例
- 配置
- 扩展
- 核心扩展
- 概览
- 自动补全
- Avro
- AWS
- Azure
- Delta
- DuckLake
- 编码
- Excel
- 全文搜索
- httpfs (HTTP 和 S3)
- Iceberg
- ICU
- inet
- jemalloc
- MySQL
- PostgreSQL
- 空间
- SQLite
- TPC-DS
- TPC-H
- UI
- VSS
- 指南
- 概览
- 数据查看器
- 数据库集成
- 文件格式
- 概览
- CSV 导入
- CSV 导出
- 直接读取文件
- Excel 导入
- Excel 导出
- JSON 导入
- JSON 导出
- Parquet 导入
- Parquet 导出
- 查询 Parquet 文件
- 使用 file: 协议访问文件
- 网络和云存储
- 概览
- HTTP Parquet 导入
- S3 Parquet 导入
- S3 Parquet 导出
- S3 Iceberg 导入
- S3 Express One
- GCS 导入
- Cloudflare R2 导入
- 通过 HTTPS / S3 使用 DuckDB
- Fastly 对象存储导入
- 元查询
- ODBC
- 性能
- Python
- 安装
- 执行 SQL
- Jupyter Notebooks
- marimo Notebooks
- Pandas 上的 SQL
- 从 Pandas 导入
- 导出到 Pandas
- 从 Numpy 导入
- 导出到 Numpy
- Arrow 上的 SQL
- 从 Arrow 导入
- 导出到 Arrow
- Pandas 上的关系型 API
- 多个 Python 线程
- 与 Ibis 集成
- 与 Polars 集成
- 使用 fsspec 文件系统
- SQL 编辑器
- SQL 功能
- 代码片段
- 故障排除
- 术语表
- 离线浏览
- 操作手册
- 开发
- 内部结构
- 为什么选择 DuckDB
- 行为准则
- 发布日历
- 路线图
- 站点地图
- 在线演示
类型转换是一种将特定数据类型的值转换为另一种数据类型中最接近的对应值的操作。与其他 SQL 引擎一样,DuckDB 支持隐式和显式类型转换。
显式转换
显式类型转换通过使用一个 CAST
表达式来执行。例如,CAST(col AS VARCHAR)
或 col::VARCHAR
显式地将列 col
转换为 VARCHAR
类型。更多信息请参阅 转换页面。
隐式转换
在许多情况下,系统会自行添加转换。这被称为 隐式 转换,例如,当调用函数时,其参数类型与函数要求不符但可以转换为所需类型时,就会发生这种情况。
隐式转换只能针对某些类型组合添加,并且通常只有当转换不会失败时才可能。例如,可以从 INTEGER
到 DOUBLE
添加隐式转换,但不能从 DOUBLE
到 INTEGER
。
考虑函数 sin(DOUBLE)
。此函数接受 DOUBLE
类型的列作为输入参数,然而,它也可以用整数调用:sin(1)
。该整数在传递给 sin
函数之前会转换为双精度浮点数。
提示:要检查一种类型是否可以隐式转换为另一种类型,请使用
can_cast_implicitly
函数。
组合转换
当不同类型的值需要组合成一个未指定的共同父类型时,系统将执行隐式转换到自动选择的父类型。例如,list_value(1::INT64, 1::UINT64)
创建一个类型为 INT128[]
的列表。在这种情况下执行的隐式转换有时比常规隐式转换更宽松。例如,BOOL
值可以转换为 INT
(其中 true
映射到 1
,false
映射到 0
),尽管这对于常规隐式转换是不可能的。
这种 组合转换 发生在比较操作 (=
/ <
/ >
)、集合操作 (UNION
/ EXCEPT
/ INTERSECT
) 以及嵌套类型构造函数 (list_value
/ [...]
/ MAP
) 中。
转换操作矩阵
特定数据类型的值并非总是可以转换为任意目标数据类型。唯一的例外是 NULL
值,它总是可以在类型之间进行转换。以下矩阵描述了支持哪些转换。当允许隐式转换时,这意味着显式转换也是可能的。
即使基于源数据类型和目标数据类型支持转换操作,这也不一定意味着转换操作在运行时会成功。
已弃用:在 0.10.0 版本之前,DuckDB 允许在函数绑定期间将任何类型隐式转换为
VARCHAR
。0.10.0 版本引入了一项 重大变更,不再允许隐式转换为VARCHAR
。可以使用old_implicit_casting
配置选项 设置来恢复旧行为。然而,请注意,此标志将在未来弃用。
有损转换
允许执行会导致精度损失的转换操作。例如,可以将带有小数位数的数字类型(例如 DECIMAL
、FLOAT
或 DOUBLE
)显式转换为整数类型(例如 INTEGER
或 BIGINT
)。数字将被四舍五入。
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
因此,即使从 INTEGER
到 TINYINT
的转换操作受支持,但对于此特定值而言,这是不可能的。可以使用 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 类型页面
上找到。