引用数据应该选择 ID, CODE 还是 NAME
在数据库中,经常会有这几个字段:ID,Code,Name,代表序号、编码(编号)和名称。比如学生,有学号和姓名,一般还有一个唯一性的ID,通过这个ID就一定不会找到2个或更多的学生。
现在的问题是,当A表指向B表,A表应该记录B表的哪个字段?
举几个例子:
1. 用户有一个属性是“性别”,用户表应该记录性别表的ID?Code?还是Name?
2. 订单有一个属性是下单用户,订单表应该记录用户表的ID?Code?还是Name?
记录Name
记录Name是指两个表通过Name建立关联。由于Name常有重复,比如人有同名同姓,属于不同上级的名称经常有重复,全国有许多个地方都叫“新乡”,所以,记录Name就会有二义性。记录Name的方案被排除。这个大家观点基本一致。但是如果是指向类似性别这种字典/术语型的,在保证Name不重复的情况下,可以记录Name,而且记录Name更直观。
争论比较大的是,记录ID还是Code?有人说有时记ID,有时记Code,所以有了进一步追问:什么情况下应该记录ID,什么情况应该记录Code?
记录ID
这里ID等同主键,通常是整数或字符串。数据库会约束它一定不能为null,一定不会重复,即是具有非空性+唯一性。通过一个ID查找数据,只能找到一条数据,或者找不到,但绝对不会找到两条(或更多)数据。而且ID天然带索引,查找速度快。ID值本身没有意义,如果是整数通常会设置成自增长,即是1,2,3这么增加上去。如果要支持分开多个库,ID还要不重复,自增长就不合适,或者实现起来复杂,灵活度也不高。代替的方案如GUID(UUID),或雪花算法及其变种,特点都是值很长(18位十进制,16或者32个字符等)。值无意义且太长导致使用有诸多不便。当需要作映射等适配功能时,ID就非常困难。比如双方约好ID=1代表男,ID=2代表女,结果到某个旧系统中一看刚好反过来,此时需要通过映射来纠正这种对应关系。如果直接将旧系统的性别表的“男”“女”记录的ID相互调换,则与外部系统是一致了,但与内部其它表(也是引用ID)就刚好相反了。所以,记录ID没有二义性,但缺少灵活性。
记录Code
引用(使用)方和被引用(定义)方约好了一套Code,双方按照这个Code值建立联系。比如员工有工号,物流单有单号。这里有个问题,Code不像ID天然具有唯一性,但可以加约束禁止重复,实际情况的Code也不应该允许重复,比如两个员工的工号相同,两个物流单的单号相同,都是要出问题的。还有个问题,Code可能为空,比如刚报到的员工暂时还没有工号,这个问题后面再谈。相对于ID,Code的优势是比较明显的,它往往按照一定的含义编制而成,值具有意义,就比较好记。如果用作与外部系统关联,效果则要看内部表之间如何关联。假如内部表是也是用Code关联,则当需与外部系统作映射时,会遇到和ID一样的问题,系统内外两头不能同时解决。假如内部是用ID关联,则可以通过调整ID与Code的关系,协调好内部的对应与外部的对应,内外可以同时解决。还是前面那个性别的例子,只需要修改旧系统里“男”的Code为1,“女”的Code为2,就好。因为系统内部引用的是ID,Code的修改不会影响系统的内部关系,却能与外部系统建立正确的关联,从而同时解决了系统内部的对应问题。
结论
到这里结论就比较清晰了:
1. 系统内部用ID关联。非空,唯一。
2. 系统间用Code关联。值有意义,灵活可映射。
更多的思考
没有工号的员工怎么办?
规定只要是员工必须有工号。如果正式工号的产生需要有流程,可以考虑给临时工号。就像上路的汽车必须有车牌,没有正式牌也得有临时牌。
感谢 螺丝钉 协助阅稿并提出修改建议。
博主简介:佘焕敏(shé),洋名 Billy Sir。
关注编程基础技术,并致力于研究软件的自动化生成。 对编程规范化、面向对象的极致使用也有着浓厚的兴趣。 同时非常希望能够写程序到65岁。
只有工匠精神,才能把常人觉得单调乏味的代码,当作作品雕刻成艺术品。
重点:这里几乎每一篇文章,都是我认真创作的,凝结了心血。写作从来都不是一件容易的事,对从小语文不好的我而言,是难上加难。而且,你发现没有,文中没有广告。这篇文章介绍了为什么要写这些文章。
![微信赞赏码](https://img2022.cnblogs.com/blog/33556/202211/33556-20221101085333455-1717538163.png)