【问题显示】 

             种子表因人为原因、使用不当或者数据库故障导致损坏,当录单时系统报错,导致无法正常录入数据;

              如下图所示。

操作单据提示主键重复_sequenceint

 

【问题剖析】

种子表为什么会坏?因为星空的业务表的种子值不是来自于业务表本身,而是另有一套种子表来维护。

单据表的种子表:Z_单据表全名(表名不同,种子表也不同)

基础资料表的种子表:Z_BAS_ITEM,Z_BAS_ITEM_L(区别于单据,不管是啥基础资料,种子表都固定死就这两表)

如果二开人员往业务表中插入数据时,其主键值不是通过星空提供的取种子值的接口获取,那么后面通过界面新增数据时,一定会出现主键冲突的问题,因为当前插入业务表的种子值并没有在种子表报备,出现种子值重复问题是迟早的事情。

星空提供的获取种子值的接口如下:

Kingdee.BOS.ServiceHelper.DBServiceHelper.GetSequenceInt32

Kingdee.BOS.ServiceHelper.DBServiceHelper.GetSequenceInt64

Kingdee.BOS.ServiceHelper.DBServiceHelper.GetSequenceString

【解决方法】

当种子表损坏出现主键冲突报错时怎么办?

/*第一步,查看报错表的当前种子值,其中z_bas_voucher为业务表t_bas_voucher的种子表*/
DBCC CHECKIDENT('z_bas_voucher', NORESEED)

/*第二步,查看报错表的主键最大值,其中t_bas_voucher为业务表,获取主键当前最大值应该查业务表而非种子表*/
DECLARE @FID bigint
SELECT @FID=ISNULL(MAX(FVOUCHERID),100001)+1 FROM t_bas_voucher
SELECT @FID

/*第三步,更新种子值(更新前对比第一步和第二步获取的值,如果第一步获取的种子值更大,则无需更新)*/
DBCC CHECKIDENT('z_bas_voucher', RESEED, @FID)

【注意事项】

种子表修复后,仍然需要去排查种子表损坏的真实原因:
1. 是否有人为操作种子表?
2. 二开获取业务表主键值的方式是否正确?(只允许通过系统提供的GetSequenceInt32,GetSequenceInt64,GetSequenceString等方法获取,严禁使用max(fid)+1的方式填充主键值)

3.数据库服务是否出现过异常断电?