Мое требование
Таблица должна поддерживать столбец статус.
Этот столбец представляет одно из 5 состояний.
первоначальный дизайн
Я решил, что могу просто сделать его целочисленным столбцом и представлять состояния с помощью числового значения.
Поскольку я не хочу, чтобы мое приложение поддерживало сопоставление целых чисел с их строковым описанием, я планирую поместить их в отдельную таблицу описания состояний (полагаясь на отношение FK).
Затем я обнаружил, что MySQL имеет тип ENUM, который точно соответствует моим требованиям. Есть ли какие-либо подводные камни при использовании типа ENUM, кроме прямой зависимости от MySQL?
см .: dev.mysql.com/doc/refman/5.0/en/enum.html






Стол было бы легче интернационализировать. Но точно так же будет и класс вне базы данных. Этот вид проверки может быть трудно отладить, если он не входит в бизнес-логику, и, как правило, не входит в обязанности специалистов по базам данных.
В качестве оптимизации это, вероятно, очень преждевременно; но OP в основном предлагает это как удобную функцию.
См. Также http://komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil/
Для изменения набора значений в ENUM требуется ALTER TABLE, который может вызвать реструктуризацию таблицы - невероятно дорогостоящая операция (реструктуризации таблицы не произойдет, если вы просто добавите одно новое значение в конец определения ENUM, но если вы удалите one, или изменить порядок, выполняется реструктуризация таблицы). В то время как изменить набор значений в таблице поиска так же просто, как INSERT или DELETE.
Невозможно связать другие атрибуты со значениями в ENUM, например, какие из них удалены, а какие могут быть помещены в раскрывающийся список в вашем пользовательском интерфейсе. Однако таблица поиска может включать дополнительные столбцы для таких атрибутов.
Очень сложно запросить ENUM, чтобы получить список отдельных значений, в основном требуя, чтобы вы запросили определение типа данных из INFORMATION_SCHEMA и проанализировали список из возвращенного BLOB. Вы можете попробовать SELECT DISTINCT status из своей таблицы, но он получит только те значения статуса, которые используются в настоящее время, а это могут быть не все значения в ENUM. Однако, если вы сохраняете значения в таблице поиска, их легко запрашивать, сортировать и т. д.
Как видите, я не большой поклонник ENUM. :-)
То же самое относится к ограничениям CHECK, которые просто сравнивают столбец с фиксированным набором значений. Хотя MySQL все равно не поддерживает ограничения CHECK.
Обновление: MySQL 8.0.16 теперь реализует ПРОВЕРИТЬ ограничения.
Спасибо, Билл, за советы. Иногда абстракции, подобные типу ENUM, могут выглядеть простыми и элегантными, но это административная бомба замедленного действия.
О, я забыл одно: ENUM не является стандартным SQL, и, как ни странно, ни одна другая база данных не поддерживает его. Таким образом, это ограничивает вашу мобильность, если вы его используете.
Кто-то проголосовал против. Когда вы голосуете против, не могли бы вы объяснить, в чем вы возражаете? Возможно, я смогу улучшить ответ.
Вам не обязательно использовать INFORMATION_SCHEMA. Используйте DESC table, просматривайте результаты, пока не найдете нужное поле, и используйте регулярное выражение для получения полей. Это не самое лучшее занятие, но и не так уж и плохо.
Нашел еще одно интересное объяснение: komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil
@Zbyszek, ах, опасно похоже ... кто был первым?
@Pacerier, я ответил на этот пост 12 декабря 2008 г. Блог по этой ссылке был написан 2 марта 2011 г.
Другие БД, которые используют, - это Postgres и MariaDB (на самом деле любая вилка MySQL, о которой я могу думать)
Я не думаю, что ответ @BillKarwin больше актуален. MySQL, Maria и Postgresql поддерживают тип ENUM.
Вот статья про сравнение скорости перечисления. Может быть, это дает какие-то подсказки. ИМХО следует ограничиться использованием фиксированного списка строк («Да / Нет», «Ребенок / Взрослый»), который с вероятностью 99% не изменится в будущем.
Перечисления в MySQL плохи по уже объясненным причинам.
Могу добавить следующий факт: Enum не обеспечивает никакой проверки на стороне сервера. Если вы вставите строку со значением, которого нет в определении перечисления, вы получите хорошее значение <empty> или NULL в БД, в зависимости от NULL-способности объявления поля перечисления.
Моя точка зрения о крошечных точках:
Подождите, так что перечисления или tinyints - это плохо? Или оба?
Совершенно уверен, что он хотел сказать, что «перечисления» плохи по объясненным причинам.
По крайней мере, в MySQL, если вы установите SQL_MODE в одну из строгих форм, вы не получите null или '', если попытаетесь вставить значение, которого нет в ENUM. Вы получите сообщение об ошибке. См. dev.mysql.com/doc/refman/5.7/en/constraint-enum.html
Если у вас много данных в вашей БД (больше данных, чем у вас есть ОЗУ), и ваши значения ENUM НИКОГДА не изменятся, я бы выбрал ENUM, а не соединение. Так должно быть быстрее. Подумайте об этом: в случае соединения вам понадобится индекс вашего внешнего ключа и индекс вашего первичного ключа в другой таблице. Как сказал Рихо, посмотрите тесты.
Тип данных ENUM начинает отсчет с 1, а не с 0, как вы указали.