SQL存储过程插入重复的OrderNumber

时间:2014-11-04 11:17:37

标签: sql sql-server stored-procedures duplicates

我在互联网上搜索了几天,没有努力,也许我无法以正确的方式提问。

我有一个像这样的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? 到现在为止,我被困在这里很长一段时间。请帮忙。

2 个答案:

答案 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() SyncLockread more)语句包围了DID技巧:)