zoukankan      html  css  js  c++  java
  • 单据号生成

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

    [仓库编码][单据类型][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 

  • 相关阅读:
    LeetCode——Generate Parentheses
    LeetCode——Best Time to Buy and Sell Stock IV
    LeetCode——Best Time to Buy and Sell Stock III
    LeetCode——Best Time to Buy and Sell Stock
    LeetCode——Find Minimum in Rotated Sorted Array
    Mahout实现基于用户的协同过滤算法
    使用Java对文件进行解压缩
    LeetCode——Convert Sorted Array to Binary Search Tree
    LeetCode——Missing Number
    LeetCode——Integer to Roman
  • 原文地址:https://www.cnblogs.com/wych/p/2337390.html
Copyright © 2011-2022 走看看