假设我们将使用以下需求将数据库规范化为第三种范式:
我需要一个电影票登记程序,可以记住客户和他们购买的门票。
我们可能会得到这样的数据库:
ticket
id
movie_name
price
customer
id
first_name然而,当我看这个的时候,由于某种原因它看起来是多余的。如果我把它分解成更小的碎片,像这样:
name
id
name
customer
id
fk_name_id
ticket
id
fk_name_id
price这是一个好办法吗?这种方法有名字吗?
发布于 2014-03-03 18:00:25
正如乔丹所说,将数据分解成一个单独的表的意义在于避免冗余数据。
你们显然意识到,我们不想这样摆桌子:
WRONG!!!
ticket
customer_name
movie_name这意味着他看的每一部电影都会重复customer_name,而观看该电影的每个人都会重复这个电影的名字。很多很多多余的名字。如果用户每次都要输入它们,很可能有时他会拼错一个名字,或者在一个名字上使用一个变体,就像我们发现我们的表包括“星球大战”、“星球大战IV”、“星球大战第四集”和“斯特拉战争”,这些都是同一部电影。各种各样的问题。
通过将客户和电影分解成单独的表,我们消除了所有的冗余。太棒了。庆祝一下。
但是,如果我们采纳您的建议,创建一个同时保存客户名称和电影名称的“名称”表,我们是否消除了任何冗余?
如果一个顾客的名字和电影一样--如果我们碰巧有一个叫“安娜·卡列尼娜”(Anna Karenina)或“约翰·卡特”(John Carter)的客户(或者可能有人给他们的孩子取名为“蝙蝠侠归来”) --你会用同样的记录存储这两部电影吗?如果没有,那么您没有保存任何冗余。每次我们读表格时,你都强迫我们多做一次连接。
如果你使用同样的记录,那就更糟了。如果您为客户“”创建记录并与电影共享id/name记录,该怎么办?然后安娜结婚了,现在她的名字是“安娜·史密斯”。如果您更新了名称记录,您不仅更改了客户的名称,而且还更改了电影的标题!这将是一件非常糟糕的事情。
当然,您可以说,如果您更改名称,您可以为新名称创建一个新记录,而不是就地更新。但是,这却使把名字划到另一张桌子上的目的化为乌有。假设当我们最初创建电影记录时,我们错误地输入了这个名字"Anna“。现在有人指出了我们的错误,我们纠正了它。但是有了“每次有变化就创造一个新记录”的逻辑,我们就必须一个一个地解决每一张售票问题。
我想你可以问用户,这是一个改变只是电影标题,只是客户的名字,或两者。但现在我们增加了另一个层次的复杂性。为了什么呢?我们的程序更复杂,查询更复杂,用户界面更复杂。作为交换,我们在节省磁盘空间方面获得了一个小小的好处,在这种情况下,客户碰巧拥有与电影标题相同的名称。
不值得这么做。
发布于 2014-03-03 17:40:09
你的第一种方法是不正确的。如果你考虑这个问题,有三个实体:
Movie和Customer之间的连接实际上是Ticket表,因此这是一个包含其他信息的关联或连接表的示例。
我不认为这个问题是“有一个实体‘名称’,客户和电影都有名字”。名称是其他实体的属性,它不是自己的实体(至少在本例中如此)。
发布于 2014-03-03 18:09:02
周的答案很好,应该被选为正确的IMHO。
不过,我想补充一点:规范化并不意味着“将类似的数据存储在单独的结构中”。这绝对不是规范化的目的,这是许多缺乏经验的数据库建模人员犯下的错误,特别是当他们有编程(OOP)背景时。
https://stackoverflow.com/questions/22153408
复制相似问题