业务表主键:从纠结到想清楚
问题的由来
设计后台服务绕不开建表,表和表之间又互相关联:user、order,order 要引用 user。于是一个不起眼但天天要面对的问题冒出来:主键怎么命名?
我倾向过 user_id 这种带表名的命名——user 表的主键就叫 user_id,order 表引用它的列也叫 user_id。理由很朴素:每个字段一眼可辨,order.user_id 指向谁不用翻表结构。
但”一眼可辨”这四个字经得起推敲吗?我把这个问题拆开来想了一遍。先把结论交底:表名冻结、术语稳定的系统——金融核心、内部管理系统这类——我会选带表名的主键;业务词汇三年一换的互联网产品,我会选 id。为什么,一个维度一个维度说。
先把两种做法摆清楚
两种做法分别长这样:
- id 命名:
user表主键叫id,order表引用列叫user_id——两边不对称。Rails、Django、MyBatis-Plus 的约定生态都是这么默认的。 - 表名命名:
user表主键就叫user_id,order表引用列也叫user_id——同名对称。金融、电信这类传统企业系统里很常见。
顺带消个歧:这是主键列的命名问题,不是”代理键 vs 自然键”(用自增 id 还是用身份证号当主键)之争——那是另一个话题。它比看上去微妙的地方在于,user_id 这个词在两种做法里含义不同:一边是 user 表的主键,一边是引用列的通用名字。很多人在这个话题里吵的其实是两件不同的事。
同一张表引用两次的时候
想清楚的第一步,是撞上一个现实场景:同一张表引用同一张表两次。订单有买家和卖家,审批流有创建人和审批人,转账有付款方和收款方——全都指向 user 表。