sql语句单据编号生成防并发
有用户反馈说发现重复单据号,检查发现以下单据号被分配给了不同的两个职工

系统中使用语句exec GetNewOrderNumber 'pwgnumber','PWG',1, @pwg_number output
来产生唯一单据号
此存储过程中获取最大值的语句如下:

if exists(select * from s_systemset(nolock) where classname=@keyname and typename=@keyvalue)
begin
begin tran
--语句段1
select @ordernumber=typename+substring(replicate('0',convert(int,8))+itemvalue,
len(replicate('0',conv ert(int,8))+itemvalue)-(convert(int,8)-1),convert(int,8))
from s_systemset(nolock)
where classname=@keyname
and typename=@keyvalue
--语句段2
update s_systemset
set itemvalue=itemvalue+1
from s_systemset
where classname=@keyname
and typename=@keyvalue
commit tran
end

|
1
|
同时开两个SQL查询窗口执行以下语句 |
窗口一:waitfor delay '00:00:05'
print '1'
declare @ordernumber varchar(20),@i int=1,@sysid int=1
while @i<=31000
begin
exec TestNewOrderNumber 'testnumber','TST',1,@ordernumber output
insert into test_log(docnumber,sysid,indate)
values (@ordernumber,@sysid,GETDATE())
set @i=@i+1
end
窗口二:
waitfor delay '00:00:06'
print '2'
declare @ordernumber varchar(20),@i int=1,@sysid int=2
while @i<=32000
begin
exec TestNewOrderNumber 'testnumber','TST',1,@ordernumber output
insert into test_log(docnumber,sysid,indate)
values (@ordernumber,@sysid,GETDATE())
set @i=@i+1
end
检查是否有重复:
select docnumber,COUNT(docnumber)
from test_log
group by docnumber
having COUNT(docnumber)>=2
测试结果如下:有8条记录重复。
在两个不同用户同一秒调用此语句后,产生了重复的Pwg_Number,为什么呢?
在SQL中已经用了事务来获取最大值,为何不同用户几乎同时调用时会返回相同的pwg_number?
尝试将语句段1和语句段2对调如下:

--将语句段1和语句段2对调
begin tran
update s_systemset --语句段2
set itemvalue=itemvalue+1
from s_systemset
where classname=@keyname
and typename=@keyvalue
--语句段1
select @ordernumber=typename+substring(replicate('0',convert(int,8))+itemvalue,len(replicate('0',convert(int,8))+itemvalue)-(convert(int,8)-1),convert(int,8))
from s_systemset(rowlock) --将nolock改为rowlock
where classname=@keyname
and typename=@keyvalue commit tran

重复在两个窗口并行测试,第一次是9万笔,第二次是90万笔,第3次10万笔。统计没有重复记录。

到这里重复单据号的问题是否算是已经得到解决了呢?
各位SQL大牛,为什么语句段一和语句段二的顺序对调后,就不会有重复了。
问题来了,以上语句真得能够保证产生唯一的最大值吗
sql语句单据编号生成防并发的更多相关文章
- C# 生成编号(防并发)
今天抽了点时间,写了一个通用的生成编号的程序! 我的生成规则为年月日+两位编号,即:yyyyMMdd+两位编号,譬如:2018101001 / 2018101002 / 2018101003 首先,一 ...
- MySQL通过SQL语句来直接生成新表
1. 既复制表结构,也复制表数据 mysql> CREATE TABLE tmp_table SELECT * FROM dede_news; 说明:这种方法的缺点就是新表中没有了旧表的prim ...
- 在sqlserver中,使用sql语句更新数据库:生成随机数,更新每一行中的年龄字段
use School --指定数据库 declare @min_id int --声明整数变量@x set @min_id=(select MIN(Id) from Students) --给变量@x ...
- SqlServer 中如何查看某一个Sql语句是复用了执行计划,还是重新生成了执行计划
我们知道SqlServer的查询优化器会将所执行的Sql语句的执行计划作缓存,如果后续查询可以复用缓存中的执行计划,那么SqlServer就会为后续查询复用执行计划而不是重新生成一个新的执行计划,因为 ...
- mysqls,为node.js而编写的sql语句生成插件 (crud for mysql).
It is written in JavaScript,crud for mysql.You can also use transactions very easily. mysqls 一款专为nod ...
- 年终巨献 史上最全 ——LINQ to SQL语句
LINQ to SQL语句(1)之Where 适用场景:实现过滤,查询等功能. 说明:与SQL命令中的Where作用相似,都是起到范围限定也就是过滤作用的,而判断条件就是它后面所接的子句.Where操 ...
- LINQ to SQL语句大全
LINQ to SQL语句大全 LINQ to SQL语句(1)之Where 适用场景:实现过滤,查询等功能. 说明:与SQL命令中的Where作用相似,都是起到范围限定也就是过滤作用的,而判 ...
- 史上最全 ——LINQ to SQL语句
LINQ to SQL语句(1)之Where 适用场景:实现过滤,查询等功能. 说明:与SQL命令中的Where作用相似,都是起到范围限定也就是过滤作用的,而判断条件就是它后面所接的子句.Where操 ...
- LINQ to SQL语句(17)之对象加载
对象加载 延迟加载 在查询某对象时,实际上你只查询该对象.不会同时自动获取这个对象.这就是延迟加载. 例如,您可能需要查看客户数据和订单数据.你最初不一定需要检索与每个客户有关的所有订单数据.其优点是 ...
随机推荐
- Track Cylinder
1 Track = 48 KB1 Cylinder = 720 KB so 1 Cylinder = 15 Tracks Read more: http://ibmmainframes.com/abo ...
- [BZOJ 4060] Word Equations
Link: BZOJ 4060 传送门 Solution: 可以发现字符串间的关系可以构成一棵树 于是我们先用字符串哈希建树,再树形$dp$即可 设$dp[i][j]$为第$i$个节点从$P$字符串的 ...
- [Codeforces 10E] Greedy Change
Brief Introduction: 给你一些种类的硬币,用最少的硬币数表示X 求最小的使贪心算法错误的X Algorithm: 一道论文题,<A Polynomial-time Algori ...
- 【贪心】bzoj3721 PA2014 Final Bazarek
考虑不限制奇偶的情况,那就是直接排序取前k个的和. 加上奇偶限制:若排序后的前k个的和是偶数,则“显然地”:将其中的最小的奇数替换成未被选择的数中最大的偶数 或者 将其中的最小的偶数替换成未被选择的数 ...
- IO流--File--properties
package com.songyan.properties; /** * properties * 是hashtable的子类具备map集合的特点 * 里面存储的键值对都是String而且不需要指定 ...
- 输入参数之POJO包装类
1,包装类:需要实现序列化 package com.songyan.pojo; import java.io.Serializable; public class QueryVo implements ...
- mysql-connector-java-6日期存储时差的问题解决方法
在my.ini文件中的[mysqld]下面加入 default-time_zone = '+8:00' 重启mysql 修改driver连接路径 这样日期保存到mysql就是正确的了,但是mysql- ...
- 设置cookie和查找cookie的方法
1.设置cookie(名称,值,过期时间) function setCookie(key,value,d){ if(d === undefined){ document.cookie = encode ...
- javascript快速入门11--正则表达式
正则表达式可以: 测试字符串的某个模式.例如,可以对一个输入字符串进行测试,看在该字符串是否存在一个电话号码模式或一个信用卡号码模式.这称为数据有效性验证 替换文本.可以在文档中使用一个正则表达式来标 ...
- http://blog.csdn.net/tkwxty/article/details/34474501
http://blog.csdn.net/tkwxty/article/details/34474501