- 安装
- 文档
- 入门
- 连接
- 数据导入
- 客户端 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
- 行为准则
- 发布日历
- 路线图
- 站点地图
- 在线演示
名称 | 描述 |
---|---|
ENUM |
表示列所有可能字符串值的字典 |
枚举类型表示一个字典数据结构,其中包含列所有可能的唯一值。例如,存储一周中各天的列可以是一个包含所有可能日期的枚举。枚举对于基数低(即,不同值较少)的字符串列尤其有用。这是因为该列仅存储枚举字典中字符串的数值引用,从而大大节省了磁盘存储并提高了查询性能。
枚举定义
枚举类型可以从硬编码的值集创建,也可以从返回单列 VARCHAR
的 SELECT 语句创建。SELECT 语句中的值集将被去重,但如果枚举是从硬编码值集创建的,则可能没有任何重复项。
使用硬编码值创建枚举
CREATE TYPE enum_name AS ENUM (value_1, value_2, ...);
使用返回单列 VARCHAR
的 SELECT
语句创建枚举
CREATE TYPE enum_name AS ENUM (select_expression);
枚举也可以在类型转换过程中动态创建
SELECT 'some_string'::ENUM (value_1, value_2, ...);
示例
创建新的用户定义类型 mood
作为枚举
CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy');
从 select 语句创建枚举。首先创建一个示例值表
CREATE TABLE my_inputs AS
FROM (VALUES ('duck'), ('duck'), ('goose')) t(my_varchar);
动态创建一个匿名枚举值
SELECT 'happy'::ENUM ('sad', 'ok', 'happy');
此语句将失败,因为枚举不能包含 NULL
值
CREATE TYPE breed AS ENUM ('maltese', NULL);
此语句将失败,因为枚举值必须是唯一的
CREATE TYPE breed AS ENUM ('maltese', 'maltese');
使用 my_varchar
列中的唯一字符串值创建枚举
CREATE TYPE birds AS ENUM (SELECT my_varchar FROM my_inputs);
使用 enum_range
函数显示 birds
枚举中的可用值
SELECT enum_range(NULL::birds) AS my_enum_range;
my_enum_range |
---|
[duck, goose] |
枚举用法
枚举创建后,可以在任何使用标准内置类型的地方使用。例如,我们可以创建一个表,其中一列引用该枚举。
创建一个表 person
,其中包含属性 name
(字符串类型)和 current_mood
(mood 类型)
CREATE TABLE person (
name TEXT,
current_mood mood
);
在 person
表中插入元组
INSERT INTO person
VALUES ('Pedro', 'happy'), ('Mark', NULL), ('Pagliacci', 'sad'), ('Mr. Mackey', 'ok');
以下查询将失败,因为 mood 类型没有 quackity-quack
值。
INSERT INTO person
VALUES ('Hannes', 'quackity-quack');
字符串 sad
被转换为 mood
类型,返回一个数值引用。这使得比较成为数值比较而不是字符串比较。
SELECT *
FROM person
WHERE current_mood = 'sad';
name | current_mood |
---|---|
Pagliacci | sad |
如果您正在从文件导入数据,您可以在导入前为 VARCHAR
列创建枚举。鉴于此,以下子查询会自动选择唯一的不同值
CREATE TYPE mood AS ENUM (SELECT mood FROM 'path/to/file.csv');
然后,您可以创建一个具有枚举类型的表,并使用任何数据导入语句进行导入
CREATE TABLE person (name TEXT, current_mood mood);
COPY person FROM 'path/to/file.csv';
枚举与字符串
DuckDB 枚举在必要时会自动转换为 VARCHAR
类型。此特性允许枚举列在任何 VARCHAR
函数中使用。此外,它还允许不同枚举列之间,或枚举与 VARCHAR
列之间的比较。
例如
Regexp_matches 是一个接受 VARCHAR 的函数,因此 current_mood 被转换为 VARCHAR
SELECT regexp_matches(current_mood, '.*a.*') AS contains_a
FROM person;
contains_a |
---|
true |
NULL |
true |
false |
创建一个新的 mood 和表
CREATE TYPE new_mood AS ENUM ('happy', 'anxious');
CREATE TABLE person_2 (
name text,
current_mood mood,
future_mood new_mood,
past_mood VARCHAR
);
由于 current_mood
和 future_mood
列是基于不同的枚举类型构建的,DuckDB 会将两个枚举都转换为字符串并执行字符串比较
SELECT *
FROM person_2
WHERE current_mood = future_mood;
在比较 past_mood
列(字符串)时,DuckDB 会将 current_mood
枚举转换为 VARCHAR
并执行字符串比较
SELECT *
FROM person_2
WHERE current_mood = past_mood;
枚举删除
枚举类型存储在目录中,并且会为每个使用它们的表添加目录依赖项。可以使用以下命令从目录中删除枚举
DROP TYPE enum_name;
目前,可以在不影响表的情况下删除表中使用的枚举。
警告:枚举删除功能的此行为可能会更改。在未来的版本中,预计在删除枚举之前必须删除任何依赖列,或者必须使用附加的
CASCADE
参数删除枚举。
枚举比较
枚举值根据其在枚举定义中的顺序进行比较。例如:
CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy');
SELECT 'sad'::mood < 'ok'::mood AS comp;
comp |
---|
true |
SELECT unnest(['ok'::mood, 'happy'::mood, 'sad'::mood]) AS m
ORDER BY m;
m |
---|
sad |
ok |
happy |
函数
参见枚举函数。