回到实体。在我们的讨论中,从第五个词开始,你不断地说"Quiz",我也这么说,但我们没有一个Entity。我无法想象一个松散和重复的问题集,在我刚刚去掉了重复项之后,没有确认所述问题集的存在。现在你可能会说"实际上测验是Topic",但是这很限制:每次老板需要为一些新客户添加测验时,他都必须重新添加整个Topic/Subtopic/Question集合,即使他知道这些确切的问题以前已经在现有的测验中输入过;这就是他赢得新业务的原因,也是他终于要盈利的原因,而你刚刚将其降至零。上次他不高兴的时候我仍然疼,所以让我们确保他没有另一个借口。这使他能够独立地增长、培育和改变测验和Topic/Subtopics,而不会重复问题:
实体。Quiz
键?好吧,它最好有一个索引,以确保我们不提供重复的测验给他。假设我们不想将CHAR(80)键带入子级,
完成了,就这样。希望我已经清楚地传达了练习是反复的,这就是为什么它被称为建模。宇航员有单独的、私人的住处,并且他们可以相互交流。
------------------------------------------------------------------------------------------
那是什么?你也想要数据模型吗?好的,给我五分钟。请自己拿杯咖啡。
------------------------------------------------------------------------------------------
它很小,我可以给您物理数据模型。我使用IDEF1X方法来建模关系数据库,这是一种标准,因此数据模型呈现为IDEF1X符号,如果您需要快速回顾符号的含义,请查看该链接。
多对多关系是一个逻辑概念,在逻辑模型中如此绘制。在物理模型中,它们作为联结表实现。我已经提供了它们。规范化的数据库有更多的表(无需担心),但每个表的列较少,没有重复的列(没有更新异常)。
我的天啊。Topic和SubTopic列非常大!我们无法将那些巨大的外键迁移到Question中。[与业务用户讨论。] 好的,他们说只会有一百个主题和几千个子主题。不需要NUMERIC(10,0)。他们希望下拉菜单中显示完整的Topic和Subtopic,并且同意它必须是唯一的,但另外一个短的CHAR(6)代码也很好。
看,它确实来回移动。纸是便宜的;与任何人讨论;改进、纠正、更改、调节、改善,而不创建单个表或编写一行代码;最终你将拥有一个值得编写代码的模型。其他任何东西都不是。学习的唯一方法是呈现出实物,并使其被拒绝或更改;在纸上犯所有错误,而不是在数据库中。
请注意,Surrogate键始终是附加键,附加索引。它们永远不会替代主键(这就是你所拥有的内容,以及Eddie试图让你考虑的内容:你没有防止重复项,你只是拥有一个无意义的键来保证行是唯一的,就像电子表格一样;和一种虚假的安全感)。因此,我们需要将它们最小化,而不是在每个表上随意打上它们。
我希望我已经表明,像“永远不要使用替代品”和“总是使用替代品”这样的简单规则太愚蠢了,无法讨论。不,仔细的建模意味着:理解并考虑它们是附加的,而不是替代真正的键。只有在必须使用时才使用,而且必须使用它们。在这里,我只使用了一个IDENTITY。对于用户有意义的三个短代码是代理,但它们具有含义;IDENTITY列没有(它们最终具有意义,但它们无法支持,这是问题的一部分)。
我会将DataTypes留给你处理。但请记住,varchars和Nullable列会强制使列变量。如果在索引中使用会非常慢(每个条目在每次访问时都必须进行一些“解包”,即使是中间级别),因此必须避免使用,除非你想提供一个缓慢的数据库。
同样,如果您不希望在每次更新时将页面上的行移动,那么应该使用固定长度的列。这意味着我们不能懒惰地使用varchar。
现在,我们有了一个容纳火箭燃料的舱室。
回复评论1
从您的最后数据模型来看,如果我在问题表中省略topicCode,是否更好?在子主题和问题表中都包含topicCode是否感觉有些冗余?
很好的问题。
(第五个是数据模型;第四个是实体关系图;前三个是空想,努力实现。)
在子表中将主键迁移为外键不是冗余的,而是必须的。
Subtopic PK 是 (TopicCode, SubtopicCode),是一个复合键(商业数据库支持的关系模型要求)。在 Subtopic 的水平线以上。
- 一些开发者害怕使用复合键,因为需要在 WHERE 子句中引用多个字段(纯粹的懒惰;SQL 在连接方面很繁琐;请应对这种情况)。
.
这是因为 Topic::Subtopic 关系是标识关系,这意味着父表的主键用于构造子表的主键,形成一个复合键。请注意,父表的主键必须在子表中作为外键存在,因此它不是冗余的,而是必须的。这已经被证明可以显著增加数据库的“功率”或“关联性”,并且大大增加了易用性(强大的用户通常比开发人员更擅长使用关系型数据库)。
- 这就是为什么它被确定为标准:IDEF1X 是一种强制执行关系模型更严格应用的标准;它促进了对所有键的深思熟虑,这当然对于假定的关系型数据库的“关联性”至关重要。
.
在问题中,因此与 Subtopic 相关的 FK 是 (TopicCode, SubtopicCode)。
如果在 Topic 和 SubTopic 中使用 ID,则 Question 将具有 (SubtopicId) 作为与 Subtopic 相关的 FK,并且您将失去导航功能和含义。
- 使用标识父项(和祖父项)的复合键比使用 ID 更优越的一个原因是,例如,当您仅需要从 Question 和 Topic 获取列时,您不必从 Subtopic 进行选择;而对于 ID,则被迫从 Subtopic 进行选择,这不是报告要求的一部分,而是由于较差的关系建模而强加的;未能实现标识关系,即强大的含义。这只是数据堆仅具有 ID 作为 PK(作为 FK 承载)执行比规范化关系型数据库更多工作的原因之一。
- 由于涉及的表格简单且小,这可能不是展示关系键优越性/IDENTITY 列限制的好例子;请考虑任何大型的 Grandparent::Parent::Child 表格。
- 展示这种优越性/限制的更好的例子,并值得任何希望进一步讨论此问题的人考虑的是我的高级课程数据模型,因为这个问题被明确地解决了。
- 另一个原因是失去了含义。例如,用户可以简单地选择 TopicCode、SubtopicCode、Question FROM Question,并理解结果集。
回应评论2
进阶数据模型101102
回应评论3
我不明白如何使用同一张图片文件来回答不同的问题?
简单的例子,"列举一种不能飞的鸟"和"什么是鸸鹋"两个问题都可以使用同一张鸸鹋的照片。这是根据上面主贴中的(1)所假设的。该模型通过在FileName上提供非唯一索引来实现。
是否应该在Question表中包含Media.FileName外键并删除Media表中的QuestionId?
好吧,不需要。我建模的方式有几个优点。如果它在Question表中,那么很大一部分时间它将为Null。你需要在Filename上建立一个索引来搜索它们;看看它是否被使用;或者没有;等等。这意味着我们不能对FileName列进行索引(或者我们可以对其进行索引,但由于Nulls,索引会很慢)。现在它的建模方式如下:
- 一个问题的"选项"或子类型(具有图像的问题)
- 没有Nulls
- 快速的非唯一索引
它可以被设置为一个图像库(唯一索引)。我们知道一个问题可以有零到一个图片。您可以告诉我们您的决定,我会更改模型:
- 图片文件名唯一;每个问题仅能使用一次
- 图片文件名唯一;可以在多个问题中使用
这是什么样的关系?1::1?
是的。媒体端是“可选的”。具体来说:一个问题有零个或一个媒体。因此,“可能有”是关系的动词短语或标题。
模型考虑了自然层次结构:父项位于子项之上;子类型处于同一水平线上。
看起来不像其他n :: n或1 :: n关系。
没有n :: n关系。(逻辑层面上有一个,但在物理层面上被实现为联接表。)
**为什么在QuizQuestion表中包含答案字段?*
你想把用户的答案存储在哪里?
你需要Quiz和QuizQuestion表;它们在之前就是有效实体,你当时没有看到,但现在你看到了。
主题和子主题之间的关系在Subtopic表中定义。在Question表中,您已经包括了TopicCode和SubtopicCode。您说(如果我没有错的话),包括TopicCode很好,因为我可以直接从Question表中获取Topic而不必加入Subtopic表。
是的。根据上述(1.子主题)。
但是,根据您的模型,每次我向数据库输入新问题时,都应该为问题选择一个主题和子主题[从现有列表中]。
好的,无论如何你都必须这样做;模型只是强制执行它。我通过数据了解到这就是你所需要的。一个子主题可以属于多个主题。因此你需要给它同时提供主题和子主题(特定的组合)。
那么这个数据库怎样保证子主题属于在子主题表中描述的某个主题呢?
你没看见吗?你能看到子主题表已经提供了具体的 [你插入的任何东西] 主题::子主题组合……而不是其他的吗?那么,当你添加一个新问题并给它一个主题和子主题(这是 SubTopic 的主键,也是 Question 的外键)时,数据库将强制执行 FK,以便只使用存在于 SubTopic 中的 Topic::Subtopic 组合之一。
这是对自然良好关系键的一点小见识。
这就是一个好的关系模型的美妙之处:它从一个单一的[正确建模的]结构中提供了许多要求。
回应评论4
进阶数据模型101103
进阶数据模型101109
IDEF1X符号表示法