SQL Server标准化策略:varchar vs int Identity
我只是想知道什么是最佳解决方案。
说我有一个规范化的数据库。整个系统的主键是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)
当然要添加其他几个一对多的关系。
你们怎么想哪个更好?为什么?
解决方案
我们真的可以使用名称作为主键吗?几个名字相同的人是否存在很高的风险?
如果我们真的很幸运,可以将name属性用作主键,那么一定要使用它。不过,通常情况下,我们必须弥补一些不足,例如customer_id等。
最后:" NAME"是至少一个DBMS中的保留字,因此请考虑使用其他名称,例如全名。
我认为,如果VARCHAR较大,我们会注意到我们正在整个数据库中复制大量数据。而如果使用数字ID列,则在将外键列添加到其他表时不会复制几乎相同数量的数据。
此外,就比较而言,文本数据是一个皇家难题,当我们在WHERE id = user_id与WHERE name喜欢inputname(或者类似名称)进行比较时,生活要轻松得多。
使用任何类型的非合成数据(即来自用户的任何内容,而不是由应用程序生成的数据)作为PK都是有问题的;我们必须担心文化/本地化的差异,区分大小写(以及其他取决于数据库排序规则的问题),如果/当用户输入的数据发生更改时,可能会导致数据问题等。
使用非用户生成的数据(顺序的GUID(如果数据库不支持它们或者我们不关心页面拆分,则为非顺序的)或者身份整数(如果我们不需要GUID),则为非顺序的)更容易并且更容易更安全。
关于重复数据:我看不到使用非合成键如何保护我们免受此伤害。我们仍然遇到问题,用户输入" Bob Smith"而不是" Bob K. Smith"或者" Smith,Bob"或者" bob smith"等。无论密钥是否为合成密钥,都必须进行重复管理(并且几乎相同)或者非合成和非合成密钥还有许多其他潜在问题,合成密钥可以很好地避免。
许多项目不需要担心这一点(例如,严格限制的排序规则选择避免了很多选择),但总的来说,我更喜欢合成键。这并不是说我们不能成功使用有机键,显然可以,但是对于许多项目而言,它们并不是更好的选择。
我相信大多数开发了任何大型实际数据库应用程序的人都会告诉我们代理密钥是唯一可行的解决方案。
我知道学术界会不同意,但这就是理论的纯正性与实用性之间的区别。
必须进行合理大小查询的任何使用非代理键的表之间的联接,其中某些表具有复合主键的查询很快就变得难以维护。
如果"名称"字段确实适合作为主键,则执行此操作。在这种情况下,通过创建代理密钥将不会使数据库更加规范化。我们将获得一些外键重复的字符串,但这不是规范化问题,因为FK约束就像在替代键上一样,保证了字符串的完整性。
但是,我们没有解释"名称"是什么。实际上,很少将字符串用作主键。如果它是一个人的名字,它将不能用作PK,因为多个人可以具有相同的名字,所以人们可以更改名字,依此类推。
其他人似乎没有提到的一件事是,在int字段上的联接往往比在varchar字段上的联接性能更好。
而且我绝对会使用代理键代替使用(人或者公司的)名称,因为随着时间的推移它们永远不会唯一。例如,在我们的数据库中,我们有164个名称,其中100多个实例具有相同的名称。这清楚地表明了考虑使用名称作为关键字段的危险。
最初的问题不是归一化。如我们所述,如果我们具有规范化的数据库,则出于规范化的原因,我们无需对其进行更改。
问题中确实有两个问题。首先是ints或者varchars是否更适合用作主键和外键。第二个问题是我们是否可以使用问题定义中提供的自然键,还是应该生成合成键(替代键)来代替自然键。
ints比varchars更为简洁,而对于诸如索引处理之类的东西则更有效。但是区别并没有压倒性的。我们可能不应仅凭此做出决定。
所提供的自然键是否真的可以用作自然键的问题更为重要。 "名称"列中重复的问题不是唯一的问题。还有一个问题,当一个人改变名字时会发生什么。在我们给出的示例中,这个问题可能不会出现,但是在其他许多数据库应用程序中都会出现。一个例子是学生修完的所有课程四年的成绩单。一个女人可能会在四年的时间内结婚并改名,但现在我们陷入了困境。
我们或者保留名称不变(在这种情况下,名称将不再与现实世界保持一致),或者在此人参加的所有课程中进行追溯更新,从而使数据库与当时制作的印刷名册不一致。
如果我们决定使用合成密钥,则现在必须决定应用程序是否要向用户社区显示合成密钥的价值。这是另一种蠕虫病毒,超出了本讨论的范围。