我在互联网上搜索了几天,没有努力,也许我无法以正确的方式提问。
我有一个像这样的SQL表:
create table Items
(
Id int identity(1,1),
OrderNumber varchar(7),
ItemName varchar(255),
Count int
)
然后我有一个存储过程插入项目,按需创建新的OrderNumber
:
create procedure spx_insertItems
@insertNewOrderNr bit,
@orderNumber varchar(7),
@itemName varchar(255),
@count int
as
begin
set nocount on;
if (@insertNewOrderNr = 1)
begin
declare @newNr = (select dbo.fun_getNewOrderNr())
INSERT INTO Items (OrderNumber, ItemName, Count) values (@newNr, @itemName, @count)
select @newNr
end
else
begin
INSERT INTO Items (OrderNumber, ItemName, Count) values (@orderNumber, @itemName, @count)
select scope_identity()
end
end
最后,有一个用户定义的函数返回新的OrderNumber
:
create function dbo.fun_getNewOrderNr
()
return varchar(7)
as
begin
/* this func works well */
declare @output varchar(7)
declare @currentMaxNr varchar(7)
set @currentMaxNr = (isnull((select max(OrderNumber) from Items), 'some_default_value_here')
/* lets assume the @currentMaxNr is '01/2014', here comes logic that increments to @newValue='02/2014' and sets to @output, so: */
set @output = @newValue
return @output
end
进入项目可以插入不属于任何OrderNumber
的项目。
项目是否应该成为新的OrderNumber
,使用@insertNewOrderNr=1
调用该过程,返回新的订单号,该订单号可用于插入OrderNumber
的{{1}}的下一个项目@insertNewOrderNr=0
1}}。
偶尔会出现同时向@insertNewOrderNr
提出2个请求并且有问题的问题 - Items
,这些请求应该与不同的OrderNumbers
相对应OrderNumber
。< / p>
我尝试使用交易但没有成功。
表格结构不能由我修改。
什么是正确的方法来确保,当同时向程序发出请求时,将不会使用相同的newOrderNumber
?
到现在为止,我被困在这里很长一段时间。请帮忙。
答案 0 :(得分:0)
只要您使用MAX(OrderNumber),就会遇到这个问题。
您可以考虑使用序列:
创建序列
CREATE SEQUENCE dbo.OrderNumbers
AS int
START WITH 1
INCREMENT BY 1
NO CACHE;
GO
CREATE SEQUENCE dbo.OrderNumberYear
AS int
START WITH 2014
INCREMENT BY 1
NO CACHE;
SELECT NEXT VALUE FOR dbo.OrderNumberYear; --Important, run this ONE time after creation, this years value must be returned one initial time to work correctly.
插入代码
DECLARE @orderNumberYear INT = (SELECT CONVERT(INT, current_value) FROM sys.sequences WHERE name = 'OrderNumberYear');
IF(@orderNumberYear < YEAR(GETDATE()))
BEGIN
SELECT @orderNumberYear = NEXT VALUE FOR dbo.OrderNumberYear;
ALTER SEQUENCE dbo.OrderNumbers RESTART WITH 1 ;
END
IF(@orderNumberYear != YEAR(GETDATE()))
RAISERROR(N'Order year sequence is out of sync.', 16, 1);
DECLARE @newNr VARCHAR(15) = CONCAT(FORMAT(NEXT VALUE FOR dbo.OrderNumbers, '00/', 'en-US'), @orderNumberYear);
INSERT INTO Items (OrderNumber, ItemName, Count) values (@newNr, @itemName, @count)
SELECT @newNr
答案 1 :(得分:0)
这种两面性仍然存在,不是经常发生,而是发生了。
我最终用来解决的技巧并没有发现自己在SQL中。由于数据库始终只由一个用户使用的一个Web应用程序使用,因此这就是解决方案:
在我的VB.NET代码中的所有(大约5个)位置我用myCommand.ExecuteScalar()
SyncLock
(read more)语句包围了DID技巧:)