enum.md 8.0 KB
Newer Older
1 2 3 4 5
---
toc_priority: 50
toc_title: Enum
---

6
# Enum {#enum}
7

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

10
Именованные значения задаются парами `'string' = integer`. ClickHouse хранит только числа, но допускает операции над ними с помощью заданных имён.
11

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

14 15
-   8-битный `Enum`. Может содержать до 256 значений, пронумерованных в диапазоне `[-128, 127]`.
-   16-битный `Enum`. Может содержать до 65536 значений, пронумерованных в диапазоне `[-32768, 32767]`.
16 17 18

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

19
## Примеры использования {#primery-ispolzovaniia}
20 21 22

Создадим таблицу со столбцом типа `Enum8('hello' = 1, 'world' = 2)`.

23
``` sql
24 25
CREATE TABLE t_enum
(
26
    x Enum('hello' = 1, 'world' = 2)
27 28 29 30
)
ENGINE = TinyLog
```

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

33
``` sql
34 35
INSERT INTO t_enum VALUES ('hello'), ('world'), ('hello')
```
36 37

``` text
38
Ok.
39
```
40 41

``` sql
42 43
insert into t_enum values('a')
```
44 45

``` text
46
Exception on client:
47
Code: 49. DB::Exception: Unknown element 'a' for type Enum('hello' = 1, 'world' = 2)
48
```
49

50 51
При запросе данных из таблицы ClickHouse выдаст строковые значения из `Enum`.

52
``` sql
53
SELECT * FROM t_enum
54
```
55 56

``` text
57 58 59 60 61 62 63
┌─x─────┐
│ hello │
│ world │
│ hello │
└───────┘
```

64 65
Если необходимо увидеть цифровые эквиваленты строкам, то необходимо привести тип `Enum` к целочисленному.

66
``` sql
67
SELECT CAST(x AS Int8) FROM t_enum
68
```
69 70

``` text
71 72 73 74 75 76 77
┌─CAST(x, 'Int8')─┐
│               1 │
│               2 │
│               1 │
└─────────────────┘
```

78
Чтобы создать значение типа `Enum` в запросе, также необходимо использовать функцию `CAST`.
79

80
``` sql
81
SELECT toTypeName(CAST('a', 'Enum(\'a\' = 1, \'b\' = 2)'))
82
```
83 84

``` text
85 86 87
┌─toTypeName(CAST('a', 'Enum(\'a\' = 1, \'b\' = 2)'))─┐
│ Enum8('a' = 1, 'b' = 2)                             │
└─────────────────────────────────────────────────────┘
88 89
```

90
## Общие правила и особенности использования {#obshchie-pravila-i-osobennosti-ispolzovaniia}
91

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

94
Ни строка, ни цифровое значение в `Enum` не могут быть [NULL](../../sql-reference/syntax.md#null-literal).
95

I
Ivan Blinkov 已提交
96
`Enum` может быть передан в тип [Nullable](nullable.md). Таким образом, если создать таблицу запросом
97

98
``` sql
99 100 101 102 103 104 105 106 107
CREATE TABLE t_enum_nullable
(
    x Nullable( Enum8('hello' = 1, 'world' = 2) )
)
ENGINE = TinyLog
```

, то в ней можно будет хранить не только `'hello'` и `'world'`, но и `NULL`.

108
``` sql
109
INSERT INTO t_enum_nullable Values('hello'),('world'),(NULL)
110 111 112
```

В оперативке столбец типа `Enum` представлен так же, как `Int8` или `Int16` соответствующими числовыми значениями.
113 114 115 116
При чтении в текстовом виде, парсит значение как строку и ищет соответствующую строку из множества значений Enum-а. Если не находит - кидается исключение.
При записи в текстовом виде, записывает значение как соответствующую строку. Если в данных столбца есть мусор - числа не из допустимого множества, то кидается исключение. При чтении и записи в бинарном виде, оно осуществляется так же, как для типов данных Int8, Int16.
Неявное значение по умолчанию - это значение с минимальным номером.

117
При `ORDER BY`, `GROUP BY`, `IN`, `DISTINCT` и т. п., Enum-ы ведут себя так же, как соответствующие числа. Например, при ORDER BY они сортируются по числовым значениям. Функции сравнения на равенство и сравнения на отношение порядка двух Enum-ов работают с Enum-ами так же, как с числами.
118 119 120 121

Сравнивать Enum с числом нельзя. Можно сравнивать Enum с константной строкой - при этом, для строки ищется соответствующее значение Enum-а; если не находится - кидается исключение. Поддерживается оператор IN, где слева стоит Enum, а справа - множество строк. В этом случае, строки рассматриваются как значения соответствующего Enum-а.

Большинство операций с числами и со строками не имеет смысла и не работают для Enum-ов: например, к Enum-у нельзя прибавить число.
122
Для Enum-а естественным образом определяется функция `toString`, которая возвращает его строковое значение.
123

124
Также для Enum-а определяются функции `toT`, где T - числовой тип. При совпадении T с типом столбца Enum-а, преобразование работает бесплатно.
125
При ALTER, есть возможность бесплатно изменить тип Enum-а, если меняется только множество значений. При этом, можно добавлять новые значения; можно удалять старые значения (это безопасно только если они ни разу не использовались, так как это не проверяется). В качестве «защиты от дурака», нельзя менять числовые значения у имеющихся строк - в этом случае, кидается исключение.
126 127

При ALTER, есть возможность поменять Enum8 на Enum16 и обратно - так же, как можно поменять Int8 на Int16.
I
Ivan Blinkov 已提交
128