Как я храню перечисления в базе данных - PullRequest
1 голос
/ 01 апреля 2011

Одна из вещей, с которыми я сталкиваюсь в базах данных, это коллекция отдельных таблиц с именем типа MessageType. Вы просматриваете их, и получается 6 или около того строк без связей с внешним ключом. Каждый раз, когда оказывается, у кого-то возникла идея сохранить тип Enumeration (Enum) в базе данных. Как оказалось, неплохая идея, поскольку вы можете добавлять параметры сортировки, мягкого удаления и тому подобное, но реализация отдельной таблицы для каждой из них имеет недостатки.

Ответы [ 5 ]

4 голосов
/ 01 апреля 2011

«Область» (или «тип») является фундаментальной частью теории отношений. По определению, это набор всех возможных значений рассматриваемого типа. (Между прочим.)

В некоторых случаях нецелесообразно или не нужно хранить набор таких значений в таблице.

  • Хранить набор не практично личных имен.
  • Не нужно хранить набор целых чисел.

Но в других случаях имеет смысл хранить множество всех возможных значений. В базе данных SQL вы можете сохранить этот набор как часть ограничения CHECK. Вы также можете сохранить этот набор в таблице. Самое большое преимущество хранения этого набора в таблице состоит в том, что нет необходимости изменять код, когда вы удивляетесь, обнаружив значение, которое вы изначально не знали, было членом этого набора.

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

А другие не могут.

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

3 голосов
/ 01 апреля 2011

Хотя перечисление является эффективным набором значений поиска, каждое из которых имеет имя и явное значение - так что вы можете утверждать, что каждое из них хорошо отображается в справочную таблицу.Если вы применяете ограничение внешнего ключа в любом месте, где хранятся перечисленные значения, вы также гарантируете, что данные всегда находятся в пределах диапазона.

1 голос
/ 01 апреля 2011

Хранение каждого типа перечисления в отдельном столбце - хороший дизайн. Хранение значений перечисления из разных типов в одном и том же столбце - плохой дизайн, даже если вы используете второй столбец для устранения неоднозначности. Если вы решили использовать отдельный столбец для каждого типа, дополнительные затраты на хранение этого столбца в собственной таблице будут минимальными.

Я бы обычно имел поле Id в этой таблице и использовал бы это поле Id в качестве цели для любых необходимых ссылок внешнего ключа на экземпляр enum. Такая таблица может быть использована для проверки и поиска.

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

1 голос
/ 01 апреля 2011

Это зависит от вашего сценария.Ранее я работал с приложениями, в которых использовал таблицы «Enum», но чаще я просто строго перечислял перечисления в своем коде, которые затем переводятся в буквенные строки, когда они фиксируются в базе данных.1003 *

public enum MessageType
{
    General,
    Comment,
    Feedback,
    Suggestions
}

Я не думаю, что есть правильный или неправильный путь.

0 голосов
/ 01 апреля 2011

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

Например, если MessageType перечисление имеет значения:

enum MessageType
{
    Alert = 1, /*each next will be incremented by 1*/
    Error,
    Log
}

Тогдасоответствующая таблица будет иметь следующую структуру:

table MessageTypes
{
    ID int,
    Name varchar(50)
}

Здесь ID содержит целочисленные значения из нашего MessageType enum (1 => «Alert», 2 => «Error», 3 => «Журнал») и используется в качестве внешнего ключа, где это необходимо.

Кроме того, в коде не остается большой необходимости манипулировать данными из таблицы MessageTypes, минимизируя таким образом размеры передаваемых данных из /в базу данных.

Например, рассмотрим следующую таблицу базы данных:

table Messages
{
    ID int,
    MessageTypeID int /*this is foreign key referring to Messages.ID*/,
    Text varchar(100)
}

В коде у нас, вероятно, будет соответствующий класс сущностей, подобный этому:

class Message
{
    int ID { get; set; }
    int MessageTypeID { get; set; }
    string Text { get; set; }
}

Итак,когда мы извлекаем сущность Message, нам не нужно извлекать соответствующую строку из таблицы MessageTypes, а также нам не нужно иметь отдельную сущность, такую ​​как MessageType.Вместо этого мы можем напрямую использовать уже известные значения enum для проверки типа сообщения:

var msg = LoadMessage(id: 101);
if (msg.MessageTypeID == (int)MessageType.Alert)
{
    Console.WriteLine("Alert: {0}", msg.Text);
}

Надеюсь, это имеет смысл.

...