Spec-Zone.ru › DuckDB

Тип данных перечисления

ИмяОписание
перечислениеКодирование словаря, представляющее все возможные строковые значения столбца.

Тип перечисления представляет собой структуру данных словаря со всеми возможными уникальными значениями столбца. Например, столбец, хранящий дни недели, может быть перечислением, содержащим все возможные дни. Перечисления особенно интересны для строковых столбцов с низкой кратностью (т.е. с меньшим количеством различных значений). Это связано с тем, что столбец хранит только числовую ссылку на строку в словаре перечисления, что приводит к огромной экономии дискового пространства и более быстрому выполнению запросов.

Определение перечисления

Типы перечислений создаются либо из набора значений, заданных вручную, либо из оператора SELECT, который возвращает один столбец VARCHAR. Набор значений в операторе SELECT будет дедуплицирован, но если перечисление создается из набора значений, заданных вручную, дубликаты могут отсутствовать.

Создание перечисления с использованием значений, заданных вручную:

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

Создание перечисления с использованием оператора SELECT, возвращающего один столбец VARCHAR:

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');

Создание перечисления из оператора SELECT. Сначала создадим пример таблицы значений:

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);

Отображение доступных значений в перечислении birds с помощью функции enum_range:

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';
namecurrent_mood
Pagliaccisad

Если вы импортируете данные из файла, вы можете создать перечисление для столбца 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

Создайте новое перечисление и таблицу:

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

Функции

См. Функции перечислений.

© Copyright 2018–2024 Stichting DuckDB Foundation
Licensed under the MIT License.
https://duckdb.org/docs/sql/data_types/enum.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API