⌘+k ctrl+k
1.1.3 (stable)
Search Shortcut cmd + k | ctrl + k
Enum Data Type
Name Description
enum 字典编码,表示列的所有可能字符串值。

枚举类型表示一个字典数据结构,其中包含列的所有可能唯一值。例如,存储星期几的列可以是一个包含所有可能日期的枚举。枚举对于基数较低(即不同值较少)的字符串列特别有用。这是因为该列只存储枚举字典中字符串的数字引用,从而大大节省磁盘存储空间并加快查询性能。

枚举定义

枚举类型可以从一组硬编码的值或从一个返回单列VARCHAR的select语句创建。select语句中的值集将被去重,但如果枚举是从一组硬编码的值创建的,则可能不会有任何重复。

使用硬编码值创建枚举:

CREATE TYPE enum_name AS ENUM ([value_1, value_2,...]);

使用返回单列VARCHARSELECT语句创建枚举:

CREATE TYPE enum_name AS ENUM (select_expression);

例如:

创建新的用户定义类型 'mood' 作为枚举:

CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy');

这将失败,因为 mood 类型已经存在:

CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy', 'anxious');

这将失败,因为枚举不能包含NULL值:

CREATE TYPE breed AS ENUM ('maltese', NULL);

这将失败,因为枚举值必须是唯一的:

CREATE TYPE breed AS ENUM ('maltese', 'maltese');

从选择语句创建一个枚举。首先创建一个值的示例表:

CREATE TABLE my_inputs AS
    SELECT 'duck'  AS my_varchar UNION ALL
    SELECT 'duck'  AS my_varchar UNION ALL
    SELECT 'goose' AS my_varchar;

使用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(情绪类型):

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';
名称 当前心情
帕利亚奇 悲伤

如果您正在从文件导入数据,您可以在导入之前为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';

枚举 vs. 字符串

DuckDB枚举在必要时会自动转换为VARCHAR类型。这一特性允许枚举列在任何VARCHAR函数中使用。此外,它还允许在不同枚举列之间或枚举列与VARCHAR列之间进行比较。

例如:

Regexp_matches 是一个接受 VARCHAR 的函数,因此 current_mood 被转换为 VARCHAR:

SELECT regexp_matches(current_mood, '.*a.*') AS contains_a
FROM person;
contains_a
NULL

创建一个新的心情和表格:

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_moodfuture_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;
公司
true
SELECT unnest(['ok'::mood, 'happy'::mood, 'sad'::mood]) AS m
ORDER BY m;
m
悲伤
好的
快乐

Functions

参见 Enum Functions