我试图在同一时间阻止多次插入,这样我就可以防止重复插入。我有两张桌子:
表B中,此表格包含4列id
,timeToken
,tokenOrder
和taken
。
我将插入的表A包含id
,createDate
和timeToken
。
我想要做的是防止表A中的timeToken
在同一时间发生多个插入的情况下没有重复值。我有以下代码:
DECLARE @ReturnValue nvarchar
SELECT Top 1 @ReturnValue=timeToken FROM TableB WHERE taken = 0 Order By tokenOrder
Update TableB SET taken = 1 WHERE timeToken = @ReturnValue
INSERT INTO TableA Values(@ReturnValue, GETDATE())
现在我考虑一下,是否可以使用TableB中的timeToken将TableA中的timeToken表自动增加?
表B样本数据:
id timeToken tokenOrder taken
1 1:00am 1 0
2 2:00am 2 0
3 3:00am 3 1
4 4:00am 4 0
5 5:00am 5 0
这就是我期望表A看起来像是在完全相同的4次调用之后会导致重复(id从5开始 - 这可能是因为我删除了旧记录)。
表格A示例数据:
id createDate timeToken
5 2014-11-22 12:45:34.243 1:00am
6 2014-11-22 12:45:34.243 2:00am
7 2014-11-22 12:45:34.243 4:00am
8 2014-11-22 12:45:34.243 5:00am
答案 0 :(得分:1)
尝试像这样重写,这应该确保你不会让TableB中的if(mapkey.equalsIgnorCase("Donhawmun"))
{
......
}
else if(mapkey.equalsIgnorCase("Geumcheongyo"))
{
....
}
行更新两次。
taken=0
见SQL Server isolation levels - 读取提交。 READ COMMITTED是Microsoft SQL Server数据库引擎的默认隔离级别。
在示例中,我将id从TableB复制到TableA,但可能不是必需的。
答案 1 :(得分:0)
我认为你可以分两步解决这个问题:
第1步:在所有请求到达后立即缓冲。
第2步:定期将自由令牌分配给缓冲的请求。
<强>制备强>
sequence
对象有助于解决任何订单歧义:
CREATE SEQUENCE dbo.Taken_Seq
START WITH 1
INCREMENT BY 1 ;
GO
辅助表将扮演缓冲区的角色:
CREATE TABLE buffer (
requester uniqueidentifier, createdate datetime, seq_value bigint, id int);
我还将使用GUID来引用要求令牌(请求者)的不同进程:
ALTER TABLE TableA add Requester uniqueidentifier;
解决方案大纲
一旦请求(由GUID标识)缓冲区消耗下一个序列值,就像这样(这里我使用newid()获取GUID,您的应用程序应该已经为您的请求分配了一个):< / p>
declare @seq bigint;
SELECT @seq = NEXT VALUE FOR dbo.Taken_Seq;
insert buffer values (newid(), getdate(), @seq, null);
现在假设有三个这样的请求同时到达,如:
declare @seq bigint;
SELECT @seq = NEXT VALUE FOR dbo.Taken_Seq;
insert buffer values (newid(), getdate(), @seq, null);
SELECT @seq = NEXT VALUE FOR dbo.Taken_Seq;
insert buffer values (newid(), getdate(), @seq, null);
SELECT @seq = NEXT VALUE FOR dbo.Taken_Seq;
insert buffer values (newid(), getdate(), @seq, null);
buffer
表的内容将如下所示:
requester createdate seq_value id
------------------------------------ ----------------------- -------------------- -----------
109B560C-155C-40BD-A13A-59D21EBEB1F8 2017-04-05 11:17:35.127 31 NULL
FAC00C2E-14AA-4502-AB5C-DDD756914653 2017-04-05 11:17:35.127 32 NULL
E95889C3-E291-4A1C-A7E8-0B8CC53D4D7B 2017-04-05 11:17:35.127 33 NULL
接下来,我们可以将每个缓冲的请求与令牌进行匹配。这将通过为我们的缓冲表中的每个请求分配id
值来完成:
; with a as
(select rn =row_number() over (order by seq_value), *
from buffer
where id is null),
b as
(
select rn=row_number() over (order by tokenOrder), *
from TableB
where taken = 0
)
update buffer set buffer.id = b.id
from buffer
join a on buffer.requester = a.requester
join b on a.rn = b.rn
现在我们的buffer
表格如下:
requester createdate seq_value id
------------------------------------ ----------------------- -------------------- -----------
109B560C-155C-40BD-A13A-59D21EBEB1F8 2017-04-05 11:17:35.127 31 1
FAC00C2E-14AA-4502-AB5C-DDD756914653 2017-04-05 11:17:35.127 32 2
E95889C3-E291-4A1C-A7E8-0B8CC53D4D7B 2017-04-05 11:17:35.127 33 3
使用buffer
加入TableB
表格以查找令牌:
select buffer.requester, tableB.* from buffer join tableB on buffer.id= tableB.id
将标记标记为:
update TableB set taken = 1 from buffer where buffer.id = TableB.id
最后,插入TableA
:
insert TableA (requester, createdate, timeToken)
select buffer.requester, buffer.createdate, TableB.timeToken
from buffer join TableB on buffer.id = TableB.id
注意:强> 显然,其中一些步骤必须包含在单个事务中