假设:
Person[id, name, city, state, country]
我最好直接在主表中存储城市名称而不是将外键存储到单独的cities
表中?出于本讨论的目的,假设城市名称是不可变的。这就是我的想法:
选项1 :将值存储为内联。
Person[id, name, city, state, country]
选项2 :指向单独表格的外键
Person[id, name, city_id, state_id, country_id]
Cities[id, name]
States[id, name]
Countries[id, name]
引用http://en.wikipedia.org/wiki/Database_normalization:“目标是隔离数据,以便可以在一个表中添加,删除和修改字段,然后通过定义的关系在数据库的其余部分传播。 “在我看来,这些好处在处理不可变数据时会飞出窗口,因为它永远不需要更新。至于插入和删除异常,我们可以使用可空列(如果需要)。
此案例的最佳做法是什么?
答案 0 :(得分:1)
Option 2: Foreign keys to a separate table
Person[id, name, city_id, state_id, country_id]
Cities[id, name]
States[id, name]
Countries[id, name]
“规范化”并不意味着“用id号替换名称”。你应该追捕那些教你的人,并用手指将它们戳在眼睛里。 (或者更好的是,两只眼睛。两根手指。)
“规范化”涉及识别列之间的关联(“功能依赖性”),并将它们隔离在不同的表中(“投影”)。规范化通过减少或消除某些类型的INSERT,UPDATE和DELETE异常来提高数据完整性。
稍后。 。 强>
人员表的一些示例数据。 。
id name city state country
--
1 John Smith York Alabama United States of America
2 John Doe York Maine United States of America
3 Jane Smith York Nebraska United States of America
4 Jane Doe York South Carolina United States of America
你是对的,原始表是2NF。它不在3NF,因为“国家”是关于{city,state}的事实。所以你可以用这两个表替换原来的人员表。
people
id name city state
--
1 John Smith York Alabama
2 John Doe York Maine
3 Jane Smith York Nebraska
4 Jane Doe York South Carolina
cities -- key is (city, state)
city state country
--
York Alabama United States of America
York Maine United States of America
York Nebraska United States of America
York South Carolina United States of America
需要注意的两件事:1)分解从原始表中删除了一列。 2)分解不涉及添加任意id号。
现在这些表格的正常形式是什么?
您可以使用国家/地区代码替换国家/地区名称,从而减少所需的存储空间您可以首先将ISO国家/地区代码与“城市”表中的其他属性一起存储。
cities -- key is (city, state)
city state country iso_cc
--
York Alabama United States of America US
York Maine United States of America US
York Nebraska United States of America US
York South Carolina United States of America US
但是通过添加一列,我们将功能依赖的数量从一个增加到四个。
{city, state} -> country
{city, state} -> iso_cc
country -> iso_cc
iso_cc -> country
我们可以通过创建国家/地区表来删除这两个传递依赖项。删除列“country”是有意义的,并保留列“iso_cc”有两个原因。 “iso_cc”列更短,人类可以读取它。由于人类可以阅读它,我们通常不必加入表“国家”。
cities -- key is (city, state)
city state iso_cc
--
York Alabama US
York Maine US
York Nebraska US
York South Carolina US
countries -- keys are iso_cc and country
iso_cc country
--
US United States of America
请注意,表“countries”有两个候选键。每列都是唯一的。根据我的经验,大多数数据库都不会强制执行这些约束。简单地用id号替换名称的开发人员经常错过第二个。 (那个“国家”是唯一的,不仅是身份证号码。)
答案 1 :(得分:0)
除了您的要点之外,规范化数据库还将标准化城市的命名。但是,您需要使用世界上所有城市填充您的城市表。否则,你最终会得到像纽约和纽约这样的东西。
除非您计划提供超出名称的城市信息(例如大小,地理坐标等),否则我会坚持使用字符串城市名称。如果您的代码是好的,那么无论何时需要,您都可以正常化。
答案 2 :(得分:0)
你当然可以有一个国家表,PK = ISO代码。只需搜索网络,您就会找到一份现成的清单。除非您的行号非常高(> 10 ^ 6),否则您不会关心地址的其余部分,或者您计划使用Dimitry指向的专用用途。
如果您决定采用这种方式,最终可能会得到一个位置表,其中PK =(CountryISO,PostalCode)和额外字段= City。
但是你要节省多少钱?