【问题标题】:Is string or int preferred for foreign keys?外键首选字符串还是整数?
【发布时间】:2011-06-16 08:53:36
【问题描述】:

我有一个包含 useridusername 列的用户表,它们都是唯一的。

useridusername 之间,哪个更好用作外键,为什么?
我老板想用字符串,可以吗?

【问题讨论】:

  • 请问为什么表中有两个唯一列?
  • 为什么他不能有两个唯一的列。比如有一个 ID、电子邮件和用户名。它们都可以是独一无二的,不是吗?
  • 我承认。愚蠢的问题。只是想知道这两列是否真的在描述同一件事。 nonnb 很好地回答了这个问题。
  • @Bill 感谢您的编辑希望改进语法。
  • @Bill 谢谢你的英语很好。想改进我的。

标签: mysql sql foreign-keys ddl


【解决方案1】:

int 会更快索引,可能是也可能不是问题,根据您提供的内容很难说

【讨论】:

    【解决方案2】:

    外键首选字符串还是整数?

    视情况而定

    Natural and Surrogate Keys 之间的权衡有很多existing discussions - 您需要决定什么适合您,以及您的组织内的“标准”是什么。

    在 OP 的情况下,有一个代理键 (int userId) 和一个自然键 (charvarchar 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 开销。

    【讨论】:

    • +1 以获得务实的答案,这两种解决方案都有其优点和缺点。就个人而言,我更喜欢代理键解决方案。
    【解决方案3】:

    一个 int 是 4 个字节,一个字符串可以是任意多个字节。因此,int 总是会表现得更好。当然,除非您坚持使用长度少于 4 个字符的用户名 :)

    此外,如果列本身的数据可以更改,则绝不应将列用作 PK/FK。用户倾向于更改他们的用户名,即使您的应用程序中现在不存在该功能,也可能在几年后会出现。当那一天到来时,您可能有 1000 个表引用该用户表,然后您必须更新事务中的所有 1000 个表,这很糟糕。

    【讨论】:

    • 外键的“更新级联”属性不是用来处理这种情况吗?还是我错过了什么?我同意 4 个字节/4 个字符的观点。但我不同意第二个论点。
    • 当然,您可以这样做,但仍然很糟糕。该更新可能会花费更多时间并创建比可接受的更多锁。但是,如果这对特定应用程序来说不是问题,请继续。不过我还是不推荐。
    【解决方案4】:

    这取决于外键:如果您的公司可以控制它,那么如果有 ID 字段,我建议使用 Int。但是,有时 ID 字段不在表中,因为另一个键可以作为备用唯一键。因此,在这种情况下,ID 字段可能是代理键。

    经验法则:外键数据类型应与主键数据类型匹配。

    这里有一个例外:不属于您公司的外键怎么办?您无法控制的数据库和 API 的外键呢?这些 ID 应始终为字符串 IMO。

    为了说服你,我问了这些问题:

    你在做数学吗?你在增加它吗?你有控制权吗? API 因更改而臭名昭著,甚至可以在其他人的数据库中更改数据类型……那么,当 int ID 变成十六进制时,它会给您带来多大的麻烦?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-20
      • 1970-01-01
      • 2016-05-15
      • 1970-01-01
      • 2021-10-21
      • 2015-03-16
      相关资源
      最近更新 更多