单据号生成

熟悉仓库管理系统的人会比较清楚,系统中统有各种各样的单据,如补货单 、进货单、出库单等等。在这里,我们先介绍一种单据编码定义规则:

 

[仓库编码][单据类型][YYMMDD][4位流水号]

 

如:0101JH1202030001

仓库编码:0101

单据类型:JH(进货)

生成日期:120203(120203)

四位流水:0001

 

上述规则是一种比较简单的编码方式,要注意的是上述的流水号在仓库、单据和日期之间不共享,即是说不同的仓库、不同的单据每天的流水号都是从1开始。

 

首先,我们采用一个表NoType,用来记录系统中的各种单据类型。

 

序号

列名

数据类型

长度

主键

允许空

默认值

说明

1

NoType

varchar

10

 

单据类型

2

NoTypeName

nvarchar

50

 

 

单据名称

 

然后,我们使用另一个表NoGenerate来记录每个仓库每种单据当日的最后生成的流水号。

 

序号

列名

数据类型

长度

主键

允许空

默认值

说明

1

Date

nchar

10

 

日期

2

NoType

varchar

10

 

类型

3

HouseCode

varchar

20

 

库房编号

4

LatestNo

int

4

((1))

最后流水号

 

使用Update更新方式

CREATE  PROCEDURE  [ dbo ]. [ ProcNoGenerateGet2 ]
       @NoType  VARCHAR( 10),
       @HouseCode  VARCHAR( 20),
       @length  INT,
       @code  VARCHAR( 200) OUTPUT
AS
 
-- 判断号码类型是否合法 
IF  NOT  EXISTS (  SELECT   0
                 FROM    NoType(NOLOCK)
                 WHERE   NoType  =  @NoType )
BEGIN   
      SET  @code = ' 0 '   
      RETURN   
END   
   
DECLARE  @LatestNo  INT   
DECLARE  @date  NCHAR( 10)   
SET  @date = CONVERT( NCHAR( 10), GETDATE(), 120)   
   
UPDATE  NoGenerate
SET      @LatestNo =LatestNo =LatestNo + 1
WHERE   Date  =  @date
         AND NoType  =  @NoType
         AND HouseCode  =  @HouseCode   
IF ( @@rowcount  =  0)
BEGIN    
      INSERT  INTO NoGenerate (Date,NoType,HouseCode)
      VALUES ( @Date, @NoType, @HouseCode)    
      SET  @latestNo = 1   
END   
   
SET  @code =dbo.NumberAddZeroPre( @LatestNo, @length)   
SET  @code = @HouseCode + @NoType + SUBSTRING( REPLACE( @date, ' - ', ''), 3, 6) + @code

 

其中,函数NumberAddZeroPre用来生成指定长度的流水号。

 

CREATE  FUNCTION  [ dbo ]. [ NumberAddZeroPre ] ( @num  INT, @len  INT)
RETURNS  VARCHAR( 20)
AS
BEGIN
     DECLARE  @str  VARCHAR( 20)
     SET  @str = CAST( @num  AS  VARCHAR)
     DECLARE  @curLen  INT
     SET  @curLen = LEN( @str)
     WHILE ( @curLen  <  @len)
           BEGIN
                 SET  @str = ' 0 ' + @str
                 SET  @curLen = @curLen + 1
           END
     RETURN  @str
END

 

使用Update方式进行单据号获取,足以满足大部情况的需求,但是在数据量和并发量大到一定程序的时候,会产生大量的数据锁,严重影响到系统性能,这时候,我们可以另一种解决方案,使用Insert方式实现流水号获取。

使用Insert插入方式

新建一表,定义主键时加上with(ignore_dup_key=on),忽略重复的记录。

 

1  CREATE  TABLE NoGenerate
2 (
3     Date  NCHAR( 10NOT  NULL,
4     NoType  VARCHAR( 10NOT  NULL,
5     HouseCode  VARCHAR( 20NOT  NULL,
6     LatestNo  INT  NOT  NULL  DEFAULT  1,
7          CONSTRAINT PK_NOGENERATE  PRIMARY  KEY (Date,NoType,HouseCode,LatestNo)
8 )
9  Go

 

新建一存储过程,采用插入的方式得到递增的流水号。

 

CREATE  PROCEDURE  [ dbo ]. [ ProcNoGenerateGet3 ]
     @NoType  varchar( 10),
     @HouseCode  varchar( 20),
     @length  int,
     @code  varchar( 200) output
AS
 
-- 判断号码类型是否合法
if  not  exists( select  0  from NoType(nolock)  where NoType = @NoType)
begin
     set  @code = ' 0 '
     return
end
 
-- 当前日期、最大流水号、是否采号成功(:成功,:未成功)
declare  @date  int  =  cast( Convert( nchar( 8), GetDate(), 112as  int)
declare  @dateS  nchar( 10=  Convert( nchar( 10), GetDate(), 120)
declare  @LatestNo  int
declare  @LatestNoOld  int
declare  @LatestDateForDel  int  =  0
declare  @LatestNoForDel  int   =  0
 
-- 删除前一天的数据
if (( select  count( 1from NoGenerateEx(nolock)  where NoType  =  @NoType  and HouseCode  =  @HouseCode) >  1500)
begin
     select  @LatestDateForDel  = T2.intDate,  @LatestNoForDel  = T2.LatestNo  from (
         select  top  1 T1. *  from (
             select  top  1500 nge.intDate,nge.LatestNo  from NoGenerateEx nge(nolock)
             where NoType  =  @NoType  and HouseCode  =  @HouseCode
             order  by nge.intDate,nge.LatestNo
        ) T1  order  by t1.intDate  desc, T1.LatestNo  desc
    ) T2
     delete  from NoGenerateEx  with(rowlock,xlock)  where  [ intDate ]  <  @LatestDateForDel  AND NoType  =  @NoType  and HouseCode  =  @HouseCode
     delete  from NoGenerateEx  with(rowlock,xlock)  where  [ intDate ]  =  @LatestDateForDel  and LatestNo  <  @LatestNoForDel  AND NoType  =  @NoType  and HouseCode  =  @HouseCode
end
 
declare  @insertRe  smallint  =  0
while( @insertRe  =  0)
BEGIN
   
     set  @LatestNo  =  isnull(( select  max(LatestNo)  from NoGenerateEx(nolock)
             where  [ intDate ]  =  @date  and NoType  =  @NoType  and HouseCode  =  @HouseCode), 0+  1
 
     -- 插入新号
     insert  into NoGenerateEx( [ intDate ],NoType,HouseCode,LatestNo) values( @date, @NoType, @HouseCode, @LatestNo
     set  @insertRe = @@ROWCOUNT
end
 
-- 返回值
set  @code  =  @HouseCode + @NoType +right( CAST( @date  as  varchar( 8)), 6) +dbo.NumberAddZeroPre( @LatestNo, @length)

 

采用此方式生成单据编码,与Update方式相比,会产生大量的数据,所以在存储过程中,需要不断的进行数据的清除,以保证性能,但是在并发比较高的情况下,优点也很明显,由于采用了Insert操作,所以不会出现锁表的现象。

 

 指定长度流水号生成参考:http://www.cnblogs.com/wych/archive/2009/08/06/1540302.html 

转载于:https://www.cnblogs.com/wych/archive/2012/02/03/2337390.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值