读书人

有关生成重复编号的有关问题

发布时间: 2012-02-19 19:43:37 作者: rapoo

有关生成重复编号的问题
各位好!现在我碰到一个问题,请帮忙解决下,谢谢了。
背景:
有一个数据表T1,里面有两个字段F1(编号) F2(人名).
有一段程序:
1、取T1表中的最大编号 select max(F1) F1 from T1
2、最大编号 + 1 为新的编号
3、把新的编号插入 T1 表:insert into T1(F1,F2) values(.....)
问题:
由于T1数据比较大,所以“取T1表中的最大编号”大概需要3秒,在3秒内可能同时有两个人执行这个代码,这样这两个人取出来的最大号是一样的。那么生成新的编号也一样,造成插入T1表有两个相同的最大号。如:
insert into T1(F1,F2) values('101','吴东') --- 第一个人执行的代码
insert into T1(F1,F2) values('101','吴西') --- 第二个人执行的代码
请问如何解决这个问题(吴西插入的编号F1应该是吴东编号F1+1)




[解决办法]
用的sql server吧,没有sequence的支持,是不灵活。

如果数据库结构不允许使用自增字段的话,建议另用一个新表,建立一个标识字段,记录这个T1表字段的当前最大值得。
每次插入T1表的时候,用这个新表的字段的最大值+1,插入进去即可。
如果是多用户访问新表获得最大值,同样存在你说的问题,这个时候我习惯用以下逻辑来处理

代码类似如下:

获得标识字段当前旧值
update 新表 set 标识字段=标识字段+1 where 标识字段=当前旧值
if update更新行数=1 then
返回当前旧值+1就是下一个最大id号
else
更新失败,可能同时被其他session更新了标识字段


用了几年了,这个代码逻辑尚未出现过问题,因为我的最大值字段就是主键,尚未报主键重复的错误。
我的最大并发用户只有6-10个而已。
看看大家的想法。

不要说用自增字段或序列号来替代哈,这样这个问题就没有问的必要了。

[解决办法]
这样,在进行插入数据之前,先取出最大的编号,然后定义一个变量等于这个最大值,在循环插入时新的编号只需取这个变量值+1即可,就不用每次都去select,插入一条后,就变量+1
[解决办法]
如果是sqlserver,可以在一个sql里:取最大,再用它插入
如果有索引,再大的表取最大值,也是很快的
[解决办法]
按你的想法来,最简单的思路,我曾经用过,很好用。

1、建立一个表,一行一列,仅记录最大编号MAX(F1),假如叫字段MF1;
2、每次取MF1 + 1写入MF1并取出该值,进行操作。若保存成功,把MF1写入你的F1,若放弃,则放弃该编号,以保证每个人取到的MF1都是最大的。

当然,这样就是会产生F1不连续,放弃操作也占用了一个编号,但是基本不影响使用。
[解决办法]

探讨

按你的想法来,最简单的思路,我曾经用过,很好用。

1、建立一个表,一行一列,仅记录最大编号MAX(F1),假如叫字段MF1;
2、每次取MF1 + 1写入MF1并取出该值,进行操作。若保存成功,把MF1写入你的F1,若放弃,则放弃该编号,以保证每个人取到的MF1都是最大的。

当然,这样就是会产生F1不连续,放弃操作也占用了一个编号,但是基本不影响使用。

[解决办法]
Delphi(Pascal) code
begin  qry.Close ;  qry.SQL.Clear ;  qry.SQL.Add('begin tran');  qry.SQL.Add('update codetest WITH (TABLOCKX) set code=code+1');  qry.ExecSQL ;  qry.Close ;  qry.SQL.Clear ;  qry.SQL.Add('select * from codetest');  qry.Open ;  form1.Caption := qry.FieldByName('code').AsString ;  qry.Close ;  qry.SQL.Clear ;  qry.SQL.Add('commit tran');  qry.ExecSQL ;end; 

读书人网 >.NET

热点推荐