如何让系统自动生成入库单号(20分)

  • 主题发起人 主题发起人 mkbss
  • 开始时间 开始时间
M

mkbss

Unregistered / Unconfirmed
GUEST, unregistred user!
做商品的入库,入库单号要以年月日组成
比如,今天是2006-05-26,那么入第一张单时,要求系统自动生成单号是20060526001,第二张是20060526002。。。。。。代码要如何控制呢
谢谢
 
要用存储过程在服务器端生成
如果在客户端生成,多客户端同时点击会重号
对存储过程不熟,先占个位置,学习一下
 
把尾号序号存在一张设置表里。每次用的时候先取出来+1,然后送回去马上再取出来,就是你需要的尾号,至于前面的时间串,自己合就是了。
 
楼上的方法在多客户端同时操作时肯定不行,我试很多次了
 
单机版的可以。网络版的就有问题了。
 
Anylib 组件,自由界面和报表的完美组合!
http://www.anylib.com
 
--声明变量
declare @newid varchar(50)
set @newid=convert(varchar(20),getdate(),112)
--查询处当天生成的最大纪录数,再加上1
select @newid=cast(count(*)+1 as varchar(20)) from 表明 where 单号 like @newid+'%'
--按照指定的格式生成@newid,组成格式为时间(yyyymmdd)+10位序号码
set @newid=convert(varchar(20),getdate(),112)+replicate('0',10-len(ltrin(rtrim(@newid))))+@newid
 
其实楼上几位讲的方法都可行,只是在多个客户端同时保存的时候可能会存在单据号重复的问题,我采用的方法是这样的:在数据保存的时候才去生成单据号,并且保存是采取缓存更新,万一重复,保存会失败,再重新保存一次就可以了
 
缓存更新怎么操作?
 
放在触发器里就行不管多少用户。
 
白乐天的方法是可以保证不重号的
取号和+1的过程在事务中用updatelock控制起来就能解决多人同时取号的问题
我的做法是开始保存操作前先做取号事务。通过该事务后虽然实际业务表中还不存在申请的最大号,但是最大号表中已经占用了这个号。其他人再来申请就只能拿到比这个号更大的号码。由于是在事务中使用了updatelock的所以其他请求在某请求没有完成申请并加1动作之前是不能申请的。也就是说数据库的事务控制自动实现了排队。
不过这种方法的缺点是当删除最大单时想要退号很困难
 
楼上的,可以给出使用updatelock的代码吗?
谢谢!
 
以下这段代码是自动生成编号的希望对你有用。
procedure TFlu.BitBtn2Click(Sender: TObject);
var
s,m: String;
i: integer;
begin
edit1.clear;
edit3.clear;
edit4.clear;
edit5.clear;
edit7.clear;
edit8.clear;
edit9.clear;
edit10.clear;
edit15.clear;
edit16.clear;
edit12.clear;
edit14.clear;
edit18.clear;
edit2.clear;
edit17.clear;
edit19.clear;
edit20.clear;
edit21.clear;
edit22.clear;
edit23.clear;
edit24.clear;
edit25.clear;
edit26.clear;
edit27.clear;
edit28.clear;
ComboBox2.text:='';
ComboBox4.text:='';
ComboBox5.text:='';
ComboBox6.text:='';
ComboBox7.text:='';
ComboBox8.text:='';
ComboBox9.text:='';

s:='桂1101-'+ FormatDateTime('yyyy',Now());
With Query1 do
begin
Close;
SQL.Clear;
SQL.Add('select max(syzh) as ss From syzgxx ');
Open;
end;
If Query1.FieldByName('ss').Value = null then
s := s + '0001'
else
begin
m:= Trim(Query1.FieldByName('ss').Value) ;
i:= StrToInt(Trim(Copy(m,12,4))) ;
if i<10 then
s:= s + '00'+ InttoStr(i +1)
else if i<99 then
s:= s + '00'+ InttoStr(i +1)
else if i<999 then
s:= s + '0'+ InttoStr(i +1)
else
s:= s +InttoStr(i +1);
end;
edit1.text:= s;
end;
 
谢谢楼上朋友的热心,不过这样的代码大家都写的出来
楼上的好像没看上面的内容“多个客户端同时保存的时候可能会存在单据号重复的问题”
这才是主要想解决的问题。
 
用数据库里的存储过程吧!!!
 
赞成使用williamlea提供的方法,我参与开发的一个大型进销存的销售单剧号也这样做的!
 
前些天我也做了这方面的东西
我把尾号序号存在一张设置表里。每次用的时候先取出来+1
这跟(白乐天)的方法是一样的,我是在保存提交到数据库的时才生成编号(存储过程在服务器端生成)的.
 
楼上的方法先将尾号将入表中,这种方法是可以的,但是比较转弯,
我用的方法是这样的:
将每台客户端设置一个编号,如A处的第五台电脑的编号是A005,那么通过A处这台电脑提交上去的单据编号是A00520060601001
其中A005:A处的005台电脑
20060601:是日期
001:流水号,第一张单据
等,这样就可以实现不重号了,当然根据这个你可以产生另几种做法啦。
如:你可以把时间微秒都可以做到里面,这样重复的机率是非常小的
 
我摘了一程序。
procedure Tslfrom.Edit11KeyPress(Sender: TObject; var Key: Char);
VAR
KV,kv1,kv2,kv3:string;
begin
if key=#13 then
begin
key:=#0;
with damo.pQuery do
begin
CLOSE;
sql.Clear ;
sql.Add('select * from data1');
prepare;
open;
last;
if damo.pQuery.RecordCount<>0
then
BEGIN
kv:=damo.pQuery.fieldbyname('ll').value ;
kv1:=copy(kv,1,8);
kv2:=copy(kv,9,3);
kv3:=copy((inttostr(year)+MM+DD),1,8);
if kv1=kv3 then
begin
if strtoint(kv2)<9 then kv2:='00'+ inttostr(strtoint(kv2)+1)
else if strtoint(kv2)<99 then kv2:='0'+inttostr(strtoint(kv2)+1);
kv:=kv1+kv2;
end else
kv:=inttostr(year)+MM+DD+'001'
END
else kv:=inttostr(year)+MM+DD+'001';
end;
label13.Caption:=kv;
 
取号之后马上进行+1操作,
如果使用使用存储过程出现重的概率很小几微秒的时间,
如果不使用存储过程,有出现重的可能性
建议用存储过程,没有问题的
 
后退
顶部