外键首选字符串还是整数?
视情况而定
在Natural and Surrogate Keys 之间的权衡有很多existing discussions - 您需要决定什么适合您,以及您的组织内的“标准”是什么。
在 OP 的情况下,有一个代理键 (int userId) 和一个自然键 (char 或 varchar username)。任一列都可以用作表的主键,无论哪种方式,您仍然可以强制另一个键的唯一性。
以下是选择一种或另一种方式时的一些注意事项:
使用代理键的情况(例如 UserId INT AUTO_INCREMENT)
如果您使用代理项(例如 UserId INT AUTO_INCREMENT)作为主键,则所有引用表 MyUsers 的表都应使用 UserId 作为外键。
但是,您仍然可以通过使用额外的 unique index 来强制 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`)
根据@Dagon,使用窄主键(如int)比使用更宽(和可变长度)的值(如varchar)具有性能和存储优势。这一好处还会影响引用MyUsers 的更多表,因为userid 的外键会更窄(要获取的字节更少)。
代理整数键的另一个好处是可以轻松更改用户名,而不会影响引用MyUsers 的表。
如果username 被用作自然键,而其他表通过username 耦合到MyUsers,则更改用户名非常不方便(因为否则会违反外键关系)。如果需要在使用 username 作为外键的表上更新用户名,则需要像 ON UPDATE CASCADE 这样的技术来保持数据完整性。
使用自然键(即用户名)的情况
使用代理键的一个缺点是,如果需要Username 列,则通过代理键引用MyUsers 的其他表将需要JOIN 回到MyUsers 表。自然键的潜在好处之一是,如果查询只需要引用 MyUsers 的表中的 Username 列,则它不需要连接回 MyUsers 来检索用户名,这将节省一些 I/ O 开销。