Подтвердить что ты не робот

Как обрабатывать перечисления без полей enum в базе данных?

Как мне реализовать поле перечисления в базе данных, которая не поддерживает перечисления? (т.е. SQLite)

Поля должны быть легко доступны для поиска с помощью "field =?" поэтому использование любого типа сериализации данных - плохая идея.

4b9b3361

Ответ 1

Использование внешнего ключа для справочной таблицы - это подход, который я использую. Фактически, я использую это, даже когда я использую базу данных, которая поддерживает 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.

Ответ 2

Чтобы ограничить возможные значения, я использовал бы внешний ключ для таблицы, содержащей элементы перечисления.

Если вы не хотите ПРИСОЕДИНИТЬСЯ к выполнению ваших поисков, тогда сделайте ключ varchar, если JOINS не проблема, тогда сделайте ключ INT и не присоединитесь, если вам не нужно искать в этом поле.

Обратите внимание, что внесение ваших перечислений в БД не позволяет проверять время компиляции значений в вашем коде (если вы не дублируете перечисление в коде.) Я обнаружил, что это большая нижняя сторона.

Ответ 3

В основном у вас есть два варианта:

  • используйте целое поле

  • используйте поле varchar

Я лично защищал бы использование varchars, потому что вы ничего не сломаете, если вы измените свой enum +, поля будут читаемы человеком, но у ints есть и pro pro, а именно производительность (размер данных является очевидным пример)

Ответ 4

Это то, что я сделал недавно

В моем hibernate сопоставлен POJO- я сохранил тип члена как String, и он является VARCHAR в базе данных.

Средство для этого принимает перечисление Существует еще один сеттер, который принимает String-, но это частный (или вы можете напрямую отображать поле - если это то, что вы предпочитаете.)

Теперь тот факт, что я использую String, инкапсулирован из всех. Для остальной части приложения мои объекты домена используют перечисление. И что касается базы данных, я использую String.

Если я пропустил ваш вопрос, прошу прощения.

Ответ 5

Я бы использовал varchar. Это не вариант для вас?