有好多开发人员在设计业务数据表时,习惯使用自增列作主键。这样设计主要是在新增数据时不用给主键列赋值,由数据库自动赋值,比较方便。

但是我们强建议作业务表设计时不要用自增列作主键。因为我们开发业务系统时,有时需要处理复杂业务逻辑,比如一个界面上处理主从表的新增,要显式引用主表的主键值,而如果这时主表的主键使用自增列,那么给从表设外键关联时就无法取到该主键值。

这时如果强制给主表赋值,数据库就会报错。比如对于sqlserver自增列主键(int identity primary key),报如下错误:com.microsoft.sqlserver.jdbc.SQLServerException:当 IDENTITY_INSERT 设置为 OFF 时,不能为表xx中的标识列插入显式值。

这时虽然可以通过在SQLServer的管理工具,执行命令:

set identity_insert tabname ON;//注:tabname换成对应表名

可以往表中插入自定义主键。但这样就失去了自增列的意义,而且会影响其它业务系统对该表进行Insert操作的功能,因为这时不提供主键值就会报错。

一般我们设计表主键时,建议用32位的GUID,比如华丹在线快速开发平台就提供了guID()函数给主键赋值。

有人可能会认为32位字符串作主键会影响效率,其实对于现在服务器硬件的高性能,这点根本不必考虑。如果真在意的话,也可以通过显式取序列值,包括通过数据库取(如oracel select SEQ_SERIAL.nextval  from dual)或是业务程序取,用数字作主键也可以。

像华丹开发平台中除了提供上述的guID()外,还提供了seqVal(subSys,seqId)取指定的序列值,而且序列还支持按年、月、日递增,并可设定序数位数。还有subSeqVal(subSys,seqId,subSeqId)支持子序列,即一种序列,可以根据子序列标识分别计数,如平台中的报表id,就是每个子系统独立计数,就是用的子序列。

最后,说明一下,主键一般不要用业务主键,即主键不要有任何业务逻辑含义,纯脆主键,比如工号就不适合作员工表主键,因为工号也可能会调整,这时可以增加一个员工ID作主键。再比如系统用户表,登录帐号不适合作主键,而建一个用户ID作主键,登录帐号可变,但要设为唯一性索引。当然有些值一旦生成不会改变,如工单号,也可以作主键。