博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
单据号生成
阅读量:6370 次
发布时间:2019-06-23

本文共 4022 字,大约阅读时间需要 13 分钟。

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

 

[仓库编码][单据类型][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(
10
NOT 
NULL,
4     NoType 
VARCHAR(
10
NOT 
NULL,
5     HouseCode 
VARCHAR(
20
NOT 
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(),
112
as 
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(
1
from 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操作,所以不会出现锁表的现象。

 

 指定长度流水号生成参考: 

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

你可能感兴趣的文章
【转】从Shell脚本内部将所有标准输出及标准错误显示在屏幕并同时写入文件的方法...
查看>>
iOS开发小技巧--利用MJExtension解决数据结构复杂的模型转换
查看>>
Python中的图形库
查看>>
Linux操作系统分析 ------------------中国科技大学
查看>>
Apache多站点实现原理和配置
查看>>
javascript类型系统——包装对象
查看>>
Android4.4中不能发送SD卡就绪广播
查看>>
解决:sudo: 无法解析主机:dinphy-500-310cn: 连接超时
查看>>
Asp.Net多线程用法1
查看>>
exFAT是支持Mac和Win的
查看>>
(转)postman中 form-data、x-www-form-urlencoded、raw、binary的区别
查看>>
js Date操作
查看>>
判断用户密码是否在警告期内(学习练习)
查看>>
sp_executesql的执行计划会被重用(转载)
查看>>
禅道项目管理软件插件开发
查看>>
Linux系统各发行版镜像下载
查看>>
JS获取键盘按下的键值event.keyCode,event.charCode,event.which的兼容性
查看>>
查看ORACLE 数据库及表信息
查看>>
腾讯、百度、阿里面试经验—(1) 腾讯面经
查看>>
Codeforces Round #374 (Div. 2) D. Maxim and Array 贪心
查看>>