ENUM - колонка, що приймає одне значення з фіксованого списку. SET - кілька значень з фіксованого списку одночасно.
CREATE TABLE orders (
status ENUM('new', 'paid', 'shipped', 'cancelled') NOT NULL DEFAULT 'new',
flags SET('gift', 'urgent', 'fragile')
);
Всередині ENUM зберігається як номер значення в списку (1-2 байти) - компактно й з перевіркою допустимих значень.
Підводні камені ENUM:
- Сортування за номером, а не за абеткою.
ORDER BY statusупорядкує в порядку оголошення (new, paid, shipped, cancelled). Інколи це зручно, частіше - несподівано. - Числа в контексті чисел.
WHERE status = 1порівнює з номером, а не з рядком'1'. ДляENUM('0', '1', '2')це джерело плутанини. - Зміна списку -
ALTER TABLE. Додати значення в кінець у MySQL 8 можна миттєво (лише метадані). Додати в середину, перейменувати чи видалити - перебудова таблиці. - Нестрогий режим: недопустиме значення перетворюється на порожній рядок
''з номером 0 замість помилки. У строгому режимі (за замовчуванням у MySQL 8) - помилка. - Перенесення між СУБД: це нестандартний тип MySQL.
SET - ще специфічніший: значення зберігаються як бітова маска (до 64 елементів), шукати за ними незручно (FIND_IN_SET), а індекси майже не допомагають. Майже завжди краще окрема таблиця зв'язку.
Альтернативи ENUM:
VARCHAR+CHECK(MySQL 8.0.16+):status VARCHAR(20) CHECK (status IN ('new', 'paid', ...))- зміна переліку не чіпає дані.- Таблиця-довідник із зовнішнім ключем - коли значення змінюються без деплою чи мають атрибути (назва, колір, порядок).
- PHP enum у застосунку + рядок у базі - логіка значень живе в коді, а база зберігає просте значення.
$table->enum() у Laravel-міграціях на MySQL створює саме нативний ENUM.