我如何在数据库中存储枚举

时间:2011-04-01 10:24:05

标签: database database-design data-binding

我现在在数据库中遇到的一件事是一个名为“MessageType”的单个表的集合。你看看它们,结果是6行左右没有外键关系。每一次,事实证明有人有想法在数据库中存储枚举(Enum)类型。事实证明,因为你可以添加排序选项,软删除等,但是每个表的单个表的实现都是有缺陷的。

5 个答案:

答案 0 :(得分:4)

“域”(或“类型”)是关系理论的基本部分。根据定义,它是所讨论类型的所有可能值的集合。 (除其他外。)

在某些情况下,将这些值集存储在表中是不切实际或不必要的。

  • 存放套装是不切实际的 个人名字。
  • 没有必要存储该集 整数。

但在其他情况下,存储所有可能值的集合是有意义的。在SQL数据库中,您可以将该集存储为CHECK约束的一部分。您还可以将该集存储在表中。将该集存储在表中的最大优点是,当您发现一个您最初不知道的值是该集合的成员时,不必更改代码。

因此,在某个理论级别,可以关系数据库中的每个列映射到包含所有可能集合的表的外键引用值。但是,当构建数据库的时候,很多这些表可能会被淘汰,因为它们不切实际或不必要。

其他人可能没有。

我不确定这是否是你的意思,但如果你看一下这种表,你就不会看到任何外键引用。相关的外键引用将始终位于其他表中,引用此组所有可能的值。

答案 1 :(得分:3)

枚举是一组有效的查找值,每个都有一个名称和一个显式值 - 所以你可以争辩说每个查找值都能很好地映射到引用表。如果在存储这些枚举值的任何位置强制执行外键约束,则还要确保数据始终在范围内。

答案 2 :(得分:1)

这取决于您的方案。在我使用“Enum”表之前我已经完成了应用程序 - 但更常见的是我在代码中只有强类型枚举,然后在提交到数据库时转换为文字字符串。

e.g。

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

我认为没有正确或错误的方式。

答案 3 :(得分:1)

将每个枚举类型存储在自己的列中是很好的设计。即使您使用第二列消除歧义,在同一列中存储来自不同类型的枚举值也是糟糕的设计。一旦您决定为每种类型使用单独的列,将该列存储在其自己的表中的额外成本是最小的。

我通常在该表中有一个Id字段,并将使用该Id字段作为枚举实例所需的任何外键引用的目标。这样的表可用于验证和查找。

对于一个大型复杂的数据库,其中包含大约500个表,这些表中约有150个是查找表的情况并不少见。

答案 4 :(得分:0)

就我个人而言,如果在其他类型的实体中使用枚举值,我认为将枚举存储在数据库中是个好主意。此外,将每个枚举存储在不同的表中是很常见的,否则外键关系将不正确。

例如,如果MessageType枚举具有值:

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

然后,相应的表将具有以下结构:

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

此处,ID包含MessageType枚举的整数值(1 =>“警报”,2 =>“错误”,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那样拥有单独的实体。相反,我们可以直接使用已知的枚举值来检查消息类型:

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

我希望这是有道理的。