我们有两张桌子。第一个包含名称(varchar)字段。第二个包含一个引用第一个表中的名称字段的字段。对于与该名称关联的每一行,将重复第二个表中的该外键。通常不鼓励使用varchar / string字段作为两个表之间的连接吗?何时是字符串字段可用作连接字段的最佳情况?
答案 0 :(得分:8)
当然可以使用varchar作为关键字段(或者只是连接的东西)。它的主要问题是基于你通常存储在varchar字段中的内容;可变数据。严格来说,关键字段的变化是不可取的。一个人的姓名,电话号码,甚至他们的SSN都可以改变。但是,即使有两个John Smiths,内部ID为3的员工也将始终为ID 3。
其次,字符串比较取决于许多挑剔的细节,例如文化,整理,空白翻译等,这些细节可能会因为没有明显原因而破坏联接。假设您使用制表空间字符\ t表示您正在加入的某个字符串。之后,您将软件更改为用3个空格替换\ t,以减少原始字符串中的字符转义。您现在已经破坏了任何需要带有转义选项卡的字符串的功能,以匹配相同但不同组成的字符串。
最后,即使给出两个完全相同的字符串,比较两个整数而不是比较两个字符串有一点性能上的好处。整数比较实际上是恒定时间。字符串比较最多是线性的,基于字符串的长度。
答案 1 :(得分:6)
通常不鼓励使用varchar / string字段作为两个表之间的连接吗?
如果有一个自然键可供使用(在现实生活中非常罕见,但州/省缩写是一个很好的例子),那么VARCHAR字段就可以了。
字符串字段可以用作连接字段的最佳情况是什么时候?
由于分配给数据类型的位,取决于数据库,但通常VARCHAR(4)或更少占用与INT相同的空间量(少于较少的字符数)。
答案 2 :(得分:3)
一般来说,您不应该使用最终用户可编辑的任何内容作为FK,因为编辑不需要一次更新,而是每个表引用该密钥一次更新。
其他人已经提到了查询的性能影响,但更新成本也值得注意。我强烈建议使用生成的密钥。
答案 3 :(得分:1)
如果您关注性能,最好的方法是创建实现潜在设计选择的表,然后使用大量数据加载它们以查看会发生什么。
理论上,非常小的字符串应该与连接中的数字一样好。实际上,它肯定取决于数据库,索引和其他实现选择。
答案 4 :(得分:1)
在关系数据库中,不应在一个表中使用引用另一个表中相同字符串的字符串。如果第二个表是查找,请为表创建标识列,然后在第一个表中引用整数值。显示数据时,请使用第二个表的连接。只需确保在第二个表中你永远不会删除记录。
唯一的例外是,如果您要创建一个存档表,您希望存储在给定时间内所选择的内容。
答案 5 :(得分:1)
有时,连接将发生在不是“连接字段”的字段上,因为这只是查询的本质(例如,识别特定列中重复记录的大多数方法)。如果您想要的查询与这些值相关,那么这就是连接所在的位置,故事结束。
如果某个字段确实标识了一行,则可以将其用作密钥。如果它可以改变(它带来问题,但不是不可克服的问题),只要它仍然是真正的标识符(它永远不会改变为另一行存在的值),它甚至可以这样做。
性能影响因常见查询和数据库而异。通过数据库,一些索引策略的类型使得它们比其他数据库更好地使用varchar和其他文本键(特别是哈希索引很好)。
常见查询可以使得即使没有哈希索引也可以使用varchar。一个典型的例子是为多语言网站存储文本。每个这样的文本都将具有与其所在语言相关的特定语言ID。但是,很少需要获得关于该语言的其他信息(它的名称等);更常见的是要么通过RFC 5646代码进行过滤,要么找出RFC 6546代码是什么。如果我们使用数字id,那么我们必须连接两种类型的查询才能获得该代码。如果我们使用代码作为ID,那么与语言相关的最常见查询根本不需要查看语言表。大多数关心语言细节的查询也不需要进行任何连接;几乎唯一一次将密钥用作外键是在更新和插入文本或删除语言时保持参照完整性。因此,虽然连接在使用时效率较低,但通过使用较少的连接,整个系统将更有效。
答案 6 :(得分:0)
这取决于数据的性质。 如果字符串是一些用户输入和更新的值,那么我可能会回避加入它。在父表和详细信息表中存储名称时可能会遇到一致性问题。
没有重复的名字?
我在使用GUID或单个字符标识符时使用字符串字段作为连接,或者当我知道字符串是自然键时(尽管我几乎总是喜欢代理)
答案 7 :(得分:0)
自然主键,如邮政编码,电话号码,电子邮件地址或用户名,按定义字符串。有独特的,相对较短的。
如果您在此类列上放置索引,则使用连接没有问题。对性能的影响通常很小。