从一个审批需求看数据库设计——联合主键的使用

时间:2022-02-02 15:26:52

最近工作挺忙,已经接近996了,所以博客更新也少了。今天忙里偷闲,分享一个最近遇到的一个数据库设计问题。业务需求是:

  • 针对一条人员信息的数据进行审批操作
  • 在进行审批时要看到审批前后数据的修改
  • 同一人员的审批数据只能存在一条
  • 审批通过后数据在正式表中生效
  • 审批通过后保存审批结果数据

业务逻辑本身并不复杂,我们可以建一个跟正式表完全相同的临时表来存储修改的数据,再增加一个审批结果来标识这条数据。

假如正式表为:

ID(pk) INFO1 info2 ...
00001 test test ...

那么我们临时表可以设计为

ID(pk) info1 info2 ... AUDIT_RESULT
00001 updated updated ... pass

这样的设计符合直觉,实现起来也很简单,但问题是这个方法的扩展性不够好。原因是正式表的字段可能有很多,这些字段的类型也千差万别。假如以后加入了新功能需要对正式表的部分字段进行修改审批,当前的临时表就不能满足了。因为临时表是以id为主键的,如果继续使用临时表,则之前的审批结果就无法保存了。为了满足今后的扩展,临时表需要重新设计。

临时表的基础上加一个字段AUDIT_TYPE ,把AUDIT_TYPE设置为主键。表结构如下:

ID(pk) AUDIT_TYPE(pk) INFO1 INFO2 ... AUDIT_RESULT
00001 01 updated updated ... pass
00001 02 updated updated ... reject

设置AUDIT_TYPE以后就可以区分出各种类型的审批,方便针对其他类似的需求进行扩展。当然实际使用的时候应该考虑业务的要求,如果业务没有潜在的扩展需求用第一个方法也是可行的。

这个设计思路可以推广到其他数据库的设计。每个月备份正式表的数据,我们就可以加一个月份作为联合主键。举个例子:

ID(pk) MONTH(pk) INFO1 INFO2 ...
00001 201801 test test ...

类似的例子还有很多,这里就不多费口舌了。