Как мне реализовать поле перечисления в базе данных, которая не поддерживает перечисления? (т.е. SQLite)
Поля должны быть легко доступны для поиска с помощью "field
=?" поэтому использование любого типа сериализации данных - плохая идея.
Как мне реализовать поле перечисления в базе данных, которая не поддерживает перечисления? (т.е. SQLite)
Поля должны быть легко доступны для поиска с помощью "field
=?" поэтому использование любого типа сериализации данных - плохая идея.
Использование внешнего ключа для справочной таблицы - это подход, который я использую. Фактически, я использую это, даже когда я использую базу данных, которая поддерживает ENUM (например, MySQL).
Для простоты я могу пропустить вездесущий "id
" для таблицы поиска и просто использовать фактическое значение, которое мне нужно в моей основной таблице, в качестве первичного ключа таблицы поиска. Таким образом, вам не нужно делать объединение, чтобы получить значение.
CREATE TABLE BugStatus (
status VARCHAR(20) PRIMARY KEY
);
INSERT INTO BugStatus (status) VALUES ('NEW'), ('OPEN'), ('FIXED');
CREATE TABLE Bugs (
bug_id SERIAL PRIMARY KEY,
summary VARCHAR(80),
...
status VARCHAR(20) NOT NULL DEFAULT 'NEW',
FOREIGN KEY (status) REFERENCES BugStatus(status)
);
Следует признать, что хранение строк занимает больше места, чем реализация ENUM
в MySQL, но если в рассматриваемой таблице миллионы строк, это вряд ли имеет значение.
Другие преимущества таблицы поиска заключаются в том, что вы можете добавлять или удалять значение из списка с помощью простого INSERT
или DELETE
, тогда как с ENUM
вы должны использовать ALTER TABLE
для переопределения списка.
Также попробуйте запросить текущий список разрешенных значений в ENUM
, например, чтобы заполнить список выбора в вашем пользовательском интерфейсе. Это большое раздражение! С таблицей поиска это легко сделать: SELECT status from BugStatus
.
Также вы можете добавить другие столбцы атрибутов в таблицу поиска, если вам нужно (например, чтобы отметить варианты, доступные только администраторам). В ENUM
вы не можете комментировать записи; это просто простые значения.
Другой вариант, кроме таблицы поиска, заключается в использовании CHECK
ограничений (при условии, что база данных поддерживает их - MySQL не поддерживает CHECK до версии 8.0.16):
CREATE TABLE Bugs (
bug_id SERIAL PRIMARY KEY,
summary VARCHAR(80),
...
status VARCHAR(20) NOT NULL
CHECK (status IN ('NEW', 'OPEN', 'FIXED'))
);
Но это использование ограничения CHECK
страдает теми же недостатками, что и ENUM
: трудно изменить список значений без ALTER TABLE
, сложно запросить список разрешенных значений, трудно аннотировать значения.
PS: оператор сравнения равенства в SQL является единственным =
. Двойной ==
не имеет смысла в SQL.
Чтобы ограничить возможные значения, я использовал бы внешний ключ для таблицы, содержащей элементы перечисления.
Если вы не хотите ПРИСОЕДИНИТЬСЯ к выполнению ваших поисков, тогда сделайте ключ varchar, если JOINS не проблема, тогда сделайте ключ INT и не присоединитесь, если вам не нужно искать в этом поле.
Обратите внимание, что внесение ваших перечислений в БД не позволяет проверять время компиляции значений в вашем коде (если вы не дублируете перечисление в коде.) Я обнаружил, что это большая нижняя сторона.
В основном у вас есть два варианта:
используйте целое поле
используйте поле varchar
Я лично защищал бы использование varchars, потому что вы ничего не сломаете, если вы измените свой enum +, поля будут читаемы человеком, но у ints есть и pro pro, а именно производительность (размер данных является очевидным пример)
Это то, что я сделал недавно
В моем hibernate сопоставлен POJO- я сохранил тип члена как String, и он является VARCHAR в базе данных.
Средство для этого принимает перечисление Существует еще один сеттер, который принимает String-, но это частный (или вы можете напрямую отображать поле - если это то, что вы предпочитаете.)
Теперь тот факт, что я использую String, инкапсулирован из всех. Для остальной части приложения мои объекты домена используют перечисление. И что касается базы данных, я использую String.
Если я пропустил ваш вопрос, прошу прощения.
Я бы использовал varchar. Это не вариант для вас?