2014-11-04 2 views
0

인터넷을 며칠이나 노력하지 않고 검색했습니다. 올바른 방법으로 질문 할 수 없습니다. 마지막으로 새를 반환하는 사용자 정의 함수가SQL 저장 프로 시저 중복 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 table Items 
(
    Id int identity(1,1), 
    OrderNumber varchar(7), 
    ItemName varchar(255), 
    Count int 
) 

:

는이 같은 SQL 테이블을 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 

Into 항목은 OrderNumber에 속하지 않는 삽입 된 항목. 아이템이 OrderNumber 새가되어야 여부

, 프로 시저가 @insertNewOrderNr=1 호출, 즉 OrderNumber@insertNewOrderNr=0 반면에 다음 항목을 삽입하는 데 사용할 수있는 새로운 주문 번호를 반환합니다.

때때로 @insertNewOrderNr-2 요청이 동시에이 올 것을이 발생하고 문제가 - Items, 같은 OrderNumber을 얻을 다른 OrderNumbers와 일치해야합니다.

나는 성공한 거래를 사용하려고했습니다.

테이블 구조는 나를 수정할 수 없습니다.

절차에 대한 동시 요청이 올 때 동일한 newOrderNumber이 사용되지 않도록하려면 무엇이 올바른 방법일까요? 나는 여기까지 오랫동안 여기에 갇혀있다. 도와주세요.

+0

fun_getNewOrderNr –

+0

에 return @newValue는 무엇입니까? @newValue는 가장 높은 기존 OrderNumber에 대해 +1되는 OrderNumber입니다. 함수 자체가 매력처럼 작동하고 값이 정확합니다 (+1 만 증가) –

+0

@paulbailey : 다시 포맷 해 주셔서 감사합니다. 지금은 더 읽기 쉽습니다. :) –

답변

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 
+0

OrderNumber의 형식은 몇 가지 규칙에 맞아야합니다 : - 형식은 01/2014, 02/2014 .. - numberst는 01,02의 숫자 시퀀스 여야합니다. - 매년 01/[year]부터 다시 시작합니다. 따라서 숫자가 하나 뿐인 새 목록이 있기 때문에 순서가 적용되지 않습니다. –

+0

MAX 함수는 OrderNumber에 문자열 값이 있지만 잘 작동합니다. –

+0

당신은 여전히 ​​같은 가치를 얻을 위험이 있습니다. 나는 변경된 제안으로 답변을 업데이트 할 것입니다. –

0

을 만듭니다.

마침내 익숙해 진 마술은 SQL 내부에서 발견되지 않았습니다. 내 VB.NET 코드의 모든 (5) 장소에서

나는 myCommand.ExecuteScalar()SyncLock와 (read more) 문을 둘러싸여 : DB를 항상 여러 사용자에 의해 사용되는 하나의 웹 응용 프로그램에서 사용되기 때문에,이 솔루션입니다 그 트릭을 했어 :)