我只是想知道最佳解决方案是什么。
假设我有一个规范化的数据库。整个系统的主键是varchar。我想知道的是我应该将这个varchar与一个int相关联以进行规范化还是留下它?离开作为varchar更简单,但它可能更优化
例如我可以
People
======================
name varchar(10)
DoB DateTime
Height int
Phone_Number
======================
name varchar(10)
number varchar(15)
或者我可以
People
======================
id int Identity
name varchar(10)
DoB DateTime
Height int
Phone_Number
======================
id int
number varchar(15)
当然,添加其他几个一对多关系。
你们都在想什么?哪个更好,为什么?
答案 0 :(得分:10)
我相信大多数已开发出任何大型真实数据库应用程序的人都会告诉您,代理键是唯一可行的解决方案。
我知道学术界不同意,但这是理论纯度和实用性之间的差异。
任何合理大小的查询必须在使用非代理键的表之间进行连接,其中某些表具有复合主键很快变得不可维护。
答案 1 :(得分:7)
你真的可以使用名字作为主键吗?是不是有几个人同名的高风险?
如果你真的很幸运,你的名字属性可以用作主键,那么 - 无论如何 - 使用它。但是,通常情况下,您必须制作一些内容,例如customer_id等。
最后:“NAME”是至少一个DBMS中的保留字,因此请考虑使用其他内容,例如:全名。
答案 2 :(得分:6)
使用任何种类的非合成数据(即来自用户的任何东西,而不是由应用程序生成的)作为PK是有问题的;您必须担心文化/本地化差异,区分大小写(以及其他问题取决于数据库整理),如果/当用户输入的数据发生变化时,可能会导致数据问题等。
使用非用户生成的数据(顺序的GUID(或不连续的,如果你的数据库不支持,或者你不关心页拆分)或身份整数(如果你不需要的GUID))是更容易,更安全。
关于重复数据:我没有看到使用非合成键如何保护您。您仍然遇到用户输入“Bob Smith”而不是“Bob K. Smith”或“Smith,Bob”或“bob smith”等问题。无论您的密钥是否是合成的,重复管理都是必要的(并且几乎完全相同)或非合成密钥和非合成密钥存在许多合成密钥巧妙避免的潜在问题。
许多项目不需要担心(例如,紧密约束的校对选择会避免其中许多项目),但一般来说我更喜欢合成密钥。这并不是说你无法用有机键成功,显然你可以,但对于许多项目来说,它们不是更好的选择。
答案 3 :(得分:3)
我认为如果您的VARCHAR较大,您会注意到您在整个数据库中复制了相当多的数据。如果您使用数字ID列,则在将外键列添加到其他表时,您不会复制几乎相同数量的数据。
此外,文字数据在比较方面是一种巨大的痛苦,当你做 WHERE id = user_id 与 WHERE名称LIKE输入名称时,你的生活会轻松得多(或类似的东西)。
答案 4 :(得分:1)
如果“name”字段确实适合作为主键,那么就这样做。在这种情况下,通过创建代理键,数据库将 not 更加规范化。您将获得一些重复的外键字符串,但这不是规范化问题,因为FK约束保证了字符串的完整性,就像在代理键上一样。
但是你没有解释“名字”是什么。在实践中,很少有字符串适合作为主键。如果它是一个人的名字,它不会作为一个PK,因为不止一个人可以有相同的名字,人们可以改变名称等等。
答案 5 :(得分:1)
其他人似乎没有提到的一件事是,int字段上的连接往往比连接varchar字段更好。
我绝对会使用代理密钥而不是使用姓名(人或企业),因为它们永远不会是唯一的。例如,在我们的数据库中,我们有164个名称,其中包含100多个同名实例。这清楚地表明了考虑使用名称作为关键领域的危险。
答案 6 :(得分:1)
最初的问题不是正常化问题。如果您有一个规范化的数据库,如您所述,那么您不需要为了标准化原因而更改它。
你的问题确实有两个问题。首先是int或varchars是否适合用作主键和外键。第二个问题是你是否可以使用问题定义中给出的自然键,或者是否应该生成合成键(代理键)来代替自然键。
整数比varchars更简洁,对索引处理这样的东西更有效。但差异并不是很大。你可能不应该单独在这个基础上做出决定。
提供的自然键是否真的作为自然键的问题更为重要。 “名称”列中重复的问题不是唯一的问题。当一个人改名时会发生什么问题。这个问题可能不会出现在您给出的示例中,但它确实存在于许多其他数据库应用程序中。一个例子是学生所有课程四年的成绩单。一个女人可能会结婚并在四年内更改她的名字,现在你被困住了。
您必须保持名称不变,在这种情况下,它不再与现实世界一致,或者在所有课程中追溯更新它,这使得数据库不同意当时制作的印刷名单。
如果确定了合成密钥,则现在必须确定应用程序是否要向用户社区显示合成密钥的值。这是另一整套蠕虫,超出了本讨论的范围。