我們在開發管理軟件的時候,常常遇到流水號(單據號、登記號)自動生成、控制和管理的問題。由於流水號
具有唯一性和連續性的特點,在實際開發過程中若處理不好,會產生流水號重復及斷號的問題。特別是多個並發用
戶同時保存一張同樣的業務單據時,系統會返回多個相同的流水號。筆者以前在開發企業ERP系統的時候,就曾出
現多個並發用戶同時保存同類型的業務單據時,系統返回相同的流水號。導致業務單據出現重復。經過多方研究,
最終筆者找到了解決方案,該方案無需對數據庫加鎖,高效又簡單,在實際應用中取得了良好的效果!現把該方案寫出來,
供同行參考批評。
客戶要求自動生成銷售單據流水號,格式為:XS-年月-該年該月的流水號。具體格式如下:XS-1702-00003,表
示2017年2月開具第3單銷售單,最大單據號為99999。根據客戶的需求,我們按以下步驟編寫流水號自動生成代碼:
一.建立業務單據總表
CREATE TABLE [dbo].[YWDJZB] (
[ID] [int] IDENTITY (1, 1) NOT NULL ,
[CKDH] [varchar] (30) NOT NULL ,
[ZD1] [varchar] (20) NULL
[ZD2] [varchar] (20) NULL
[ZD3] [varchar] (20) NULL
) ON [PRIMARY]
GO
YWDJZB為業務單據總表 ,CKDH為流水號,具有唯一性和連續性的特點,所以設置為主鍵,防止重復。ZD1,ZD2,ZD3為
單據總表其他字段,可根據實際業務修改。
二.建立流水號生成存取過程(SQL SERVER數據庫)
CREATE PROCEDURE GETCKDH
@getckdh VARCHAR(50),--流水號類型
@dwmc VARCHAR(500),--@dwmc為要保存的單據記錄,用戶可根據實際需要傳遞[YWDJZB]表的記錄,
@RETURNDA VARCHAR(150) OUTPUT
AS
declare
@DWGQ VARCHAR(50),--生成的單據流水號變量
@SQLSTR NVARCHAR(1000)--SQL語句
select @DWGQ=MaxValue from ( Select Max(Cast(RIGHT(CKDH,5) as Int))+1 as MaxValue from
YWDJZB where CKDH like @getckdh+'%') AS TEMPDATA --自動生成最新的單據流水號變量
if len(@DWGQ)<>0
begin
while len(@DWGQ)<5
begin
set @DWGQ='0'+@DWGQ
End
set @DWGQ=@getckdh+@DWGQ
end
else
begin
set @DWGQ=@getckdh+'00001'
end
select @SQLSTR='insert into YWDJZB (ckdh,ZD1,ZD2,ZD3) values('+''''+@DWGQ+''''+@dwmc
--根據最新的流水號保存單據記錄
exec sp_executesql @SQLSTR
if EXISTS (select * from YWDJZB where CKDH=@DWGQ)
begin
set @RETURNDA=@DWGQ
end
else
begin
set @RETURNDA='error'
end
return
GO
三.管理軟件調用,筆者采用DELPHI開發管理軟件,具體代碼如下:
........
SQL.Add(' EXECUTE GETCKDH :getckdh, :dwmc, :RETURNDA Output ') ;
Parameters.Items[0].Value := getckdh;
dwmc:=','''+ZD1BL+''','''+ZD2BL+''','''+ZD3BL+''');//用戶可根據實際需要傳遞[YWDJZB]表的記錄
Parameters.Items[1].Value := dwmc;//
Prepared;
ExecSQL;
result:=Parameters.Items[2].Value;
........
若SQL SERVER數據庫成功生成流水號並保存以下記錄:
into YWDJZB (ckdh,ZD1,ZD2,ZD3) values(''流水號'',''字段1'',,''字段2'',,''字段3''),並自動返回自動生
成的流水號給后台軟件,若處理失敗,就返回"error"提示,后台軟件可根據返回信息提醒軟件操作員。