Перейти к основному содержимому
Перейти к основному содержимому

Enum

Перечисляемый тип, состоящий из именованных значений.

Именованные значения могут быть объявлены в виде пар 'string' = integer или просто имен 'string'. ClickHouse хранит только числа, но поддерживает операции с значениями через их имена.

ClickHouse поддерживает:

  • 8-битный Enum. Он может содержать до 256 значений, перечисленных в диапазоне [-128, 127].
  • 16-битный Enum. Он может содержать до 65536 значений, перечисленных в диапазоне [-32768, 32767].

ClickHouse автоматически выбирает тип Enum, когда данные вставляются. Вы также можете использовать типы Enum8 или Enum16, чтобы быть уверенными в размере хранения.

Примеры использования

Здесь мы создаем таблицу с колонкой типа Enum8('hello' = 1, 'world' = 2):

CREATE TABLE t_enum
(
    x Enum('hello' = 1, 'world' = 2)
)
ENGINE = TinyLog

Аналогично, вы можете опустить числа. ClickHouse автоматически назначит последовательные числа. По умолчанию номера присваиваются, начиная с 1.

CREATE TABLE t_enum
(
    x Enum('hello', 'world')
)
ENGINE = TinyLog

Вы также можете указать допустимое начальное число для первого имени.

CREATE TABLE t_enum
(
    x Enum('hello' = 1, 'world')
)
ENGINE = TinyLog
CREATE TABLE t_enum
(
    x Enum8('hello' = -129, 'world')
)
ENGINE = TinyLog
Исключение на сервере:
Код: 69. DB::Exception: Значение -129 для элемента 'hello' выходит за диапазон Enum8.

Колонка x может хранить только значения, перечисленные в определении типа: 'hello' или 'world'. Если вы попробуете сохранить любое другое значение, ClickHouse вызовет исключение. 8-битный размер для этого Enum выбирается автоматически.

INSERT INTO t_enum VALUES ('hello'), ('world'), ('hello')
Ок.
INSERT INTO t_enum values('a')
Исключение на клиенте:
Код: 49. DB::Exception: Неизвестный элемент 'a' для типа Enum('hello' = 1, 'world' = 2)

Когда вы запрашиваете данные из таблицы, ClickHouse выводит строковые значения из Enum.

SELECT * FROM t_enum
┌─x─────┐
│ hello │
│ world │
│ hello │
└───────┘

Если вам нужно увидеть числовые эквиваленты строк, вы должны привести значение Enum к целочисленному типу.

SELECT CAST(x, 'Int8') FROM t_enum
┌─CAST(x, 'Int8')─┐
│               1 │
│               2 │
│               1 │
└─────────────────┘

Чтобы создать значение Enum в запросе, также необходимо использовать CAST.

SELECT toTypeName(CAST('a', 'Enum(\'a\' = 1, \'b\' = 2)'))
┌─toTypeName(CAST('a', 'Enum(\'a\' = 1, \'b\' = 2)'))─┐
│ Enum8('a' = 1, 'b' = 2)                             │
└─────────────────────────────────────────────────────┘

Общие правила и использование

Каждому из значений присваивается число в диапазоне -128 ... 127 для Enum8 или в диапазоне -32768 ... 32767 для Enum16. Все строки и числа должны быть различными. Пустая строка разрешена. Если этот тип указан (в определении таблицы), числа могут быть в произвольном порядке. Однако порядок не имеет значения.

Ни строковое, ни числовое значение в Enum не могут быть NULL.

Enum может содержаться в типе Nullable. Таким образом, если вы создадите таблицу с помощью запроса

CREATE TABLE t_enum_nullable
(
    x Nullable( Enum8('hello' = 1, 'world' = 2) )
)
ENGINE = TinyLog

в ней могут храниться не только 'hello' и 'world', но и NULL.

INSERT INTO t_enum_nullable Values('hello'),('world'),(NULL)

В ОЗУ колонка Enum хранится так же, как Int8 или Int16 соответствующих числовых значений.

При чтении в текстовом формате ClickHouse анализирует значение как строку и ищет соответствующую строку из набора значений Enum. Если она не найдена, вызывается исключение. При чтении в текстовом формате строка считывается, и соответствующее числовое значение ищется. Исключение будет вызвано, если оно не найдено. При записи в текстовом формате значение записывается как соответствующая строка. Если данные колонки содержат мусор (числа, которые не из допустимого набора), будет вызвано исключение. При чтении и записи в двоичном формате это работает так же, как для типов данных Int8 и Int16. Неявное значение по умолчанию - это значение с самым низким номером.

Во время выполнения ORDER BY, GROUP BY, IN, DISTINCT и так далее, Enums ведут себя так же, как соответствующие числа. Например, ORDER BY сортирует их численно. Операторы равенства и сравнения работают так же на Enums, как и на базовых числовых значениях.

Значения Enum не могут быть сравнены с числами. Enums можно сравнивать с постоянной строкой. Если сравниваемая строка не является допустимым значением для Enum, будет вызвано исключение. Оператор IN поддерживается с Enum на левой стороне и набором строк на правой стороне. Строки являются значениями соответствующего Enum.

Большинство числовых и строковых операций не определены для значений Enum, например, сложение числа с Enum или конкатенация строки с Enum. Однако у Enum есть естественная функция toString, которая возвращает его строковое значение.

Значения Enum также можно преобразовать в числовые типы с помощью функции toT, где T - это числовой тип. Когда T соответствует базовому числовому типу перечисления, это преобразование не требует затрат. Тип Enum можно изменить без затрат с помощью ALTER, если изменяется только набор значений. Возможно как добавление, так и удаление членов Enum с помощью ALTER (удаление безопасно только в том случае, если удаляемое значение никогда не использовалось в таблице). В качестве меры предосторожности изменение числового значения ранее определенного члена Enum вызовет исключение.

С помощью ALTER возможно изменить Enum8 на Enum16 или наоборот, так же как и изменить Int8 на Int16.