2011-04-01 128 views
1

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

回答

3

尽管枚举是一组有效的查找值,但每个都有一个名称和一个显式值 - 所以您可以争辩说每一个查询值都很好地映射到参考表。如果您在存储这些枚举值的任何位置实施外键约束,则还要确保数据始终在范围内。

1

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

例如

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

我不认为有一个正确或错误的方式。

1

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

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

对于一个大型且复杂的数据库,其中一个大约有500个表,其中大约150个表为查找表并不罕见。

4

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

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

  • 存储个人名称集 是不实际的。
  • 没有必要存储整数的集合 。

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

所以,在一定的理论水平,你可以列在关系数据库映射到外键引用包含所有可能的值的表。但是当建立一个数据库的时候,很多这些表可能会被淘汰,无论是不切实际的还是不必要的。

而其他人可能不会。

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

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 = >“Alert”,2 = >“Error”,3 = >“Log”),并在需要时用作外键。

另外,在代码中,仍然没有很大的需要来操纵来自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); 
} 

我希望这是有道理的。