XMe*_*Men 11 mysql sql ddl foreign-keys
我有一个带有userid和username列的用户表,两者都是唯一的.
介于userid和之间username,哪个更好用作外键?为什么?
我的老板想要使用字符串,那可以吗?
Stu*_*tLC 27
看起来你有一个代理键(int userId)和一个自然键(char或varchar username).这两列都可以用作表的主键,无论哪种方式,您仍然可以强制执行另一个键的唯一性.
现在有很多关于自然和代理键之间权衡的讨论 - 你需要决定什么对你有用,以及你组织内的'标准'是什么.
选择这种或那种方式时需要考虑以下几点:
使用代理键的情况(例如UserId INT AUTO_INCREMENT)
如果使用代理(例如UserId INT AUTO_INCREMENT)作为主键,则引用表的所有表MyUsers应该UserId用作外键.
但是,您仍然可以username通过使用其他唯一索引来强制执行列的唯一性,例如:
CREATE TABLE `MyUsers` (
`userId` int NOT NULL AUTO_INCREMENT,
`username` varchar(100) NOT NULL,
... other columns
PRIMARY KEY(`userId`),
UNIQUE KEY UQ_UserName (`username`)
Run Code Online (Sandbox Code Playgroud)
根据@Dagon,使用窄主键(如a int)比使用更宽(和可变长度)的值具有性能和存储优势varchar.这种好处也影响了更多的参考表MyUsers,作为userid缩小的外键.
代理整数键的另一个好处是可以轻松更改用户名而不影响表引用MyUsers.如果将username其用作自然键,则将表连接到MyUsersvia username,这使得更改用户名更加不方便(因为否则会违反外键关系).如果在使用username外键的表上需要更新用户名,则需要使用ON UPDATE CASCADE等技术来保持数据完整性.
使用自然键的情况(即用户名)
在使用代理键的不利方面,通过代理键引用的其他表MyUsers将始终需要join返回MyUsers表以检索用户名.Natural键的一个潜在好处是,如果查询只需要Username表引用的列MyUsers,则它不需要联接回来MyUsers检索用户名,这将节省一些开销.
一个 int 是 4 个字节,一个 string 可以有任意多个字节。因此,int 总是会表现得更好。当然,除非您坚持使用长度小于 4 个字符的用户名:)
此外,如果列中的数据本身可以更改,则永远不应该将列用作 PK/FK。用户倾向于更改他们的用户名,即使您的应用程序中目前不存在该功能,也许几年后就会出现。当那一天到来时,您可能有 1000 个表引用该用户表,然后您必须更新事务中的所有 1000 个表,这很糟糕。