Я видел ряд вопросов, таких как этот , спрашивающих совета о том, как хранить перечисления в БД. Но мне интересно, зачем ты это делаешь. Итак, допустим, что у меня есть сущность Person
с gender
полем и Gender
перечислением. Тогда в моей личной таблице есть пол столбца.
Помимо очевидной причины обеспечения правильности, я не понимаю, зачем создавать дополнительную таблицу gender
для отображения того, что у меня уже есть в приложении. И мне не очень нравится иметь это дублирование.
Ответы:
Давайте возьмем другой пример, который менее чреват концепциями и ожиданиями. У меня есть перечисление здесь, и это набор приоритетов для ошибки.
Какую ценность вы храните в базе данных?
Таким образом, я мог бы хранить
'C'
,'H'
,'M'
и'L'
в базе данных. Или'HIGH'
и так далее. Это имеет проблему со строковыми данными. Существует известный набор допустимых значений, и если вы не сохраните этот набор в базе данных, с ним может быть сложно работать.Почему вы храните данные в коде?
У вас есть
List<String> priorities = {'CRITICAL', 'HIGH', 'MEDIUM', 'LOW'};
или что-то на этот счет в коде. Это означает, что у вас есть различные сопоставления этих данных в правильном формате (вы вставляете все заглавные буквы в базу данных, но отображаете их какCritical
). Ваш код теперь также трудно локализовать. Вы связали представление идеи в базе данных со строкой, которая хранится в коде.Везде, где вам нужен доступ к этому списку, вам нужно иметь дублирование кода или класс с кучей констант. Ни один из которых не является хорошим вариантом. Не следует также забывать, что существуют другие приложения, которые могут использовать эти данные (которые могут быть написаны на других языках - в веб-приложении Java используется система отчетов Crystal Reports и пакетное задание Perl, передающее данные в него). Механизму создания отчетов потребуется знать действительный список данных (что произойдет, если в
'LOW'
приоритете ничего не отмечено и вам нужно знать, что это допустимый приоритет для отчета?), А пакетное задание будет содержать информацию о том, что является действительным значения есть.Гипотетически, вы можете сказать: «Мы - магазин с одним языком - все написано на Java», и у вас есть один файл .jar, содержащий эту информацию, - но теперь это означает, что ваши приложения тесно связаны друг с другом, а этот файл .jar содержит данные. Вам нужно будет выпускать часть отчетов и пакетного обновления вместе с веб-приложением каждый раз, когда происходят изменения, и надеяться, что этот выпуск пройдет гладко для всех частей.
Что происходит, когда ваш начальник хочет другого приоритета?
Ваш босс пришел сегодня. Там новый приоритет -
CEO
. Теперь вам нужно пойти и изменить весь код, а затем выполнить перекомпиляцию и повторное развертывание.При использовании подхода enum-in-the-table вы обновляете список enum, чтобы иметь новый приоритет. Весь код, который получает список, извлекает его из базы данных.
Данные редко стоят отдельно
С приоритетами ключи данных в других таблицах, которые могут содержать информацию о рабочих процессах, или кто может установить этот приоритет или еще много чего.
Возвращаясь к полу, как упомянуто в вопросе, немного: у Пола есть ссылка на используемые местоимения:
he/his/him
иshe/hers/her
... и вы хотите избежать жесткого кодирования этого в самом коде. А потом приходит ваш босс, и вам нужно добавить, что у вас есть'OTHER'
пол (чтобы все было просто), и вам нужно соотнести этот пол сthey/their/them
... и ваш босс видит, что есть у Facebook и ... ну, да.Ограничив себя битом данных со строковым типом, а не таблицей перечисления, теперь вам нужно было реплицировать эту строку в кучу других таблиц, чтобы поддерживать эту связь между данными и другими битами.
А как насчет других хранилищ данных?
Независимо от того, где вы храните это, тот же принцип существует.
priorities.prop
который имеет список приоритетов. Вы читаете этот список из файла свойств.У вас может быть база данных хранилища документов (например, CouchDB ), в которой есть запись для
enums
(а затем написать функцию проверки в JavaScript ):Вы можете получить XML-файл с небольшой схемой:
Основная идея та же самая. В самом хранилище данных должен храниться и применяться список допустимых значений. Размещая это здесь, легче рассуждать о коде и данных. Вам не нужно беспокоиться о проверке того, что у вас есть каждый раз (верхний регистр или нижний? Почему
chritical
в этом столбце есть тип? И т. Д.), Потому что вы знаете, что вы получаете из хранилища данных точно то, что хранилище данных ожидает от вас отправлять в противном случае - и вы можете запросить хранилище данных для получения списка допустимых значений.Еда на вынос
Набор допустимых значений - это данные , а не код. Вам действительно нужно стремиться к СУХОМУ коду - но проблема дублирования заключается в том, что вы дублируете данные в коде, а не уважаете их место в качестве данных и сохраняете их в базе данных.
Это облегчает написание нескольких приложений для хранилища данных и позволяет избежать случаев, когда вам нужно будет развертывать все, что тесно связано с самими данными - потому что вы не связали свой код с данными.
Это облегчает тестирование приложений, потому что вам не нужно повторно тестировать все приложение при
CEO
добавлении приоритета - потому что у вас нет кода, который заботится о фактическом значении приоритета.Возможность рассуждать о коде и данных независимо друг от друга облегчает поиск и исправление ошибок при выполнении технического обслуживания.
источник
Как вы думаете, какие из них с большей вероятностью приведут к ошибкам при чтении запроса?
Или же
Люди создают таблицы enum в SQL, потому что считают последние более читабельными, что приводит к меньшему количеству ошибок при написании и поддержке SQL.
Вы можете сделать гендерные строки непосредственно внутри
Person
, но тогда вам придется попытаться применить кейс. Вы также можете увеличить попадание памяти в таблицу и время запроса из-за разницы между строками и целыми числами в зависимости от того, насколько хороша ваша БД при оптимизации вещей.источник
Я не могу поверить, что люди еще не упоминали об этом.
Иностранные ключи
Сохраняя перечисление в вашей базе данных и добавляя внешний ключ в таблицу, содержащую значение перечисления, вы гарантируете, что ни один код никогда не введет неправильные значения для этого столбца. Это помогает сохранить целостность данных и является наиболее очевидной причиной, по которой в IMO должны быть таблицы для перечислений.
источник
Я в лагере, который согласен с тобой. Если вы сохраните перечисление Gender в своем коде и tblGender в своей базе данных, у вас могут возникнуть проблемы в период обслуживания. Вам нужно будет документально подтвердить, что эти две сущности должны иметь одинаковые значения и, следовательно, любые изменения, которые вы вносите в одну, вы также должны вносить в другую.
Затем вам нужно будет передать значения перечисления в ваши хранимые процедуры следующим образом:
Но подумайте, как бы вы это сделали, если бы хранили эти значения в таблице базы данных:
Конечно, реляционные базы данных создаются с учетом объединений, но какой запрос легче читать?
Вот еще один пример запроса:
Сравните это с этим:
Вот еще один пример запроса:
Обратите внимание, что в этом примере вам необходимо преобразовать гендерную ячейку в результатах из int в enum. Однако эти преобразования просты. Сравните это с этим:
Все эти запросы меньше по размеру и более удобны для сопровождения, если вы хотите сохранить определения enum вне базы данных.
источник
Я бы создал таблицу Genders по той причине, что ее можно использовать при анализе данных. Я мог бы найти всех лиц мужского или женского пола в базе данных, чтобы создать отчет. Чем больше способов просмотра ваших данных, тем легче будет найти актуальную информацию. Очевидно, что это очень простое перечисление, но для сложных перечислений (таких как страны мира или государства) проще создавать специализированные отчеты.
источник
Во-первых, вам необходимо решить, будет ли база данных использоваться только одним приложением или существует возможность использования ее несколькими приложениями. В некоторых случаях база данных является не чем иным, как форматом файла для приложения (базы данных SQLite часто могут использоваться в этом отношении). В этом случае битовое дублирование определения перечисления в виде таблицы часто может быть хорошо и может иметь больше смысла.
Однако, как только вы захотите рассмотреть возможность доступа к базе данных нескольких приложений, тогда таблица для перечисления имеет большой смысл (другие ответы более подробно описаны в разделе «Почему»). Другая вещь, которую стоит рассмотреть, захочет ли вы или другой разработчик взглянуть на необработанные данные базы данных. Если это так, это может рассматриваться как другое применение приложения (только в том случае, когда лабораторный индикатор является сырым SQL).
Если у вас есть перечисление, определенное в коде (для более чистого кода и проверки времени компиляции), а также таблица в базе данных, я бы порекомендовал добавить модульные тесты, чтобы убедиться, что они синхронизированы.
источник
Если у вас есть перечисление кода, которое используется для управления бизнес-логикой в коде, вы все равно должны создать таблицу для представления данных в БД по многим причинам, подробно описанным выше / ниже. Вот несколько советов, чтобы убедиться, что значения вашей БД синхронизированы со значениями кода:
Не делайте поле идентификатора в таблице столбцом идентификации. Включить идентификатор и описание в качестве полей.
Сделайте что-то другое в таблице, чтобы разработчики знали, что значения являются полустатическими / привязаны к перечислению кода. Во всех других справочных таблицах (обычно там, где значения могут быть добавлены пользователями) у меня обычно есть LastChangedDateTime и LastChangedBy, но отсутствие их в таблицах, связанных с перечислением, помогает мне помнить, что они могут изменяться только разработчиками. Документируйте это.
Создайте проверочный код, который проверяет, что каждое значение в перечислении находится в соответствующей таблице, и что только соответствующие значения находятся в соответствующей таблице. Если у вас есть автоматизированные «тесты работоспособности» приложения, которые запускаются после сборки, то у него там. Если нет, сделайте так, чтобы код автоматически запускался при запуске приложения при каждом запуске приложения в IDE.
Создайте производственные сценарии SQL, которые делают то же самое, но внутри БД. Если они созданы правильно, они также помогут с миграцией среды.
источник
Зависит также от того, кто имеет доступ к данным. Если у вас есть только одно приложение, которое может подойти. Если вы добавите в хранилище данных или систему отчетности. Им нужно будет знать, что означает этот код, какова версия кода, которую можно редактировать для человека.
Обычно таблица типов не дублируется как перечисление в коде. Вы можете загрузить таблицу типов в список, который кэшируется.
Часто типа приходят и уходят. Вам понадобится дата, когда новый тип был добавлен. Знайте, когда был удален определенный тип. Отображать только при необходимости. Что, если клиент хочет «транссексуал» как пол, а другие - нет? Вся эта информация лучше всего хранится в базе данных.
источник