我有一段时间没有设计数据库,我现在对我的设计没有太多信心。我基本上在数据库中有三个表,表示各种历史记录。我必须改变这个系统,以便每次添加记录(例如某些东西变成历史记录)时,可能需要来自用户的一些输入。有时他们只会有一个简单的问题,有时他们会被要求提供五种不同的信息,而这些信息需要由最终用户通过管理前端灵活管理。所以我计划有一个Question表和Answer表,用复合表将这些表与其他三个表联系起来。我正在努力设计答案表,因为每个问题都需要各种各样的答案。一些响应将是通过外键绑定到另一个数据库的下拉选择。其他可以是文本输入,日期或是/否答案。现在,我有一个答案表,其中包含所有类型的答案以及一系列可以为空的字段......
+----------------------------+
| Answer |
+----------------------------+
| Id (int) |
| QuestionId (int) |
| ForeignKeyId1* (int) |
| ForeignKeyId2* (int) |
| ForeignKeyId3* (int) |
| Number* (bigint) |
| DateField* (date) |
| Text* (varchar 500) |
| YesNo* (bit) |
+----------------------------+
*Nullable
附注:问题表与QuestionType相关联,该类型将指示(在应用程序内)如何验证用户输入。输入存储在Answer记录中的适当可空字段中,其他字段为空。我认为这比捕获所有varchar应答字段没有数据完整性更好。
这是一个糟糕的设计吗?什么能让它变得更好?
答案 0 :(得分:1)
根据您的描述,您的解决方案看起来应该可以正常工作。我已经对表格进行了类似的设置,这些表格设置了列以记录特定类型的数据,允许其他字段可以为空。看起来不错,虽然我不确定您的ForeignKeyID字段是什么:\
答案 1 :(得分:1)
对于不同的数据类型具有不同的字段是可以的,因为具有多个外键。此设计将尽可能多的数据域完整性推送到DBMS中。这在哲学上是一个很好的方法,因为大多数人会告诉你让DMBS为你工作将节省你编写和维护代码。我大部分时间都会成为那些人之一。
从可维护性方面来看,还有另一种方法可以解决这个问题。如果您添加新类型的数据类型(例如浮点数或GUID),您将不得不返回并修改ANSWER表的结构。类似地,如果您创建另一个需要新查找表答案的问题类型,则必须返回并添加另一个FK字段。
你可以改变你的ANSWER表来使用catch-all方法,所以看起来更像是这样:
ANSWER
( Id (int)
, QuestionId (int)
, Part (int)
, Value (nvarchar 1000)
)
如果我正确地理解了你的问题,那么一个问题可能有多部分的答案。假设单个问题可能存在多个答案,并且您的问题控制表知道哪个部分是哪个,您可以使用“部件”字段来区分这些部件。如果每个问题只有零个或一个答案,那么您不需要答案表,只需添加答案即可。
那么,为什么你想放弃让数据库强制执行数据域完整性呢?以下是相对的利弊:
多个单独答案字段的优点:
抓住所有答案字段的优点:
在任何一种情况下,您都必须编写一些代码来处理这样一个事实:您在一个数据存储中存储了多个问题的语义不同的答案。您必须决定要编写哪种类型的额外代码,确定要放置和找到每种类型答案的类型,或者确定如何使用公共表示来存储和解释不同数据类型的类型(即字符串) )。
鉴于修改一个包含数据的表是一件痛苦的事情,并且考虑到大多数编程语言都内置了非常强大的.ToString()/ .TryParse()类型功能,我倾向于使用全能方法如果我主要担心的是可维护性。