2013-06-12 10 views
3

我有一個存儲過程,如何使此示例SQL Atomic?

ALTER PROCEDURE [dbo].[InsertDealGallery] 
(
    @ImageID INT, 
    @DealID INT 
) 
AS 

    DECLARE @MaxOrder INT; 
    SELECT @MaxOrder = MAX([Order]) + 1 FROM DealGallery WHERE DealID = @DealID 

    IF (@MaxOrder IS NULL) 
    BEGIN 
     SET @MaxOrder = 1; 
    END 



    INSERT INTO [DealGallery] 
       ([ImageID] 
       ,[DealID] 
       ,[Order]) 
     VALUES 
       (@ImageID 
       ,@DealID 
       ,@MaxOrder) 

但我擔心這是不是原子,因爲在同一時間MaxOrder可能會保持在當前的線程相同。那麼如何使這個原子?

+1

什麼你基本上是在這裏做手工計算整數標識字段。 – STLDeveloper

+0

@STL開發者,是的。我需要做這個原子 – user960567

+0

任何你不能存儲記錄被添加來控制訂單的時間的原因嗎?似乎它在功能上等同於你在這裏要做的事情。 –

回答

1

嘗試這一個 -

ALTER PROCEDURE [dbo].[InsertDealGallery] 
(
    @ImageID INT, 
    @DealID INT 
) 
AS BEGIN 

    INSERT INTO dbo.DealGallery (ImageID, DealID, [Order]) 
    SELECT 
      @ImageID 
     , @DealID 
     , ISNULL(MAX(d.[Order]) + 1, 1) 
    FROM (SELECT a = 1) t 
    LEFT JOIN dbo.DealGallery d ON d.DealID = @DealID 

END 

或者嘗試這一個 -

INSERT INTO dbo.DealGallery (ImageID, DealID, [Order]) 
    SELECT 
      @ImageID 
     , @DealID 
     , ISNULL(m, a) 
    FROM (SELECT a = 1) t 
    LEFT JOIN (
     SELECT m = MAX(d.[Order]) + 1 
     FROM dbo.DealGallery d 
     WHERE d.DealID = @DealID 
    ) t2 ON 1 = 1 
+0

獲取錯誤'相關名't'在FROM子句中多次指定。' – user960567

+0

我會測試並讓你知道嗎? – user960567

+0

好的。經過測試,請告訴你的結果。 – Devart

0

這應該工作:插入最大爲了增加一個當交易編號在DealGallery表中找到否則插入最大順序0

BEGIN TRAN 

    INSERT INTO [DealGallery] 
        ([ImageID] 
        ,[DealID] 
        ,[Order]) 
    SELECT @ImageID, @DealID, MAX([Order]) + 1 
    FROM DealGallery WHERE DealID = @DealID 
    UNION 
    SELECT @ImageID, @DeadID, 1 
    FROM (SELECT 1 AS C) AS T 
    WHERE NOT EXISTS (SELECT * FROM DealGallery WHERE DealID = @DealID) 

COMMIT TRAN 
+0

交易是必需的嗎? – user960567

+0

您需要更改ISOLATION LEVEL;這不像寫入那樣是併發安全的。 –

3

交易是爲了獲得原子的行爲特徵。你知道來自ACID的是Atomic。 但是你選擇了一個非常糟糕的設計,aggegration函數可以鎖定所有行,性能變得非常差。

編輯

你應該搬到identitat數據類型。另外還有另一種技術,如櫃檯桌,但簡單的方法是身份。

要將代碼包含在事務中,您應該包含「開始事務」和「提交」句子。

編輯2

這種方法,爲每個Deal一個計數器,將避免鎖定所有DealGallery的行,只鎖定DealGalleryCounter行。

CREATE TABLE DealGalleryCounter 
    (DealID INT not null primary key, 
    order int default 0 
); -- Or add column to an existing deal table. 

ALTER PROCEDURE [dbo].[InsertDealGallery] 
(
    @ImageID INT, 
    @DealID INT 
) 
AS BEGIN 
    DECLARE @order int 

    begin transaction 
    set transaction isolation level serializable 
    -- repeatable read is enough -- 

    select @order = order + 1 
     from DealGalleryCounter 
    where @DealID = DealID 

    if @order is null 
     insert into DealGalleryCounter (DealID) values (@DealID) 

    INSERT INTO dbo.DealGallery (ImageID, DealID, [Order]) 
    VALUES (@ImageID, @DealID, @order); 

    update DealGallery 
     set DealGalleryCounter = @order 
    where @DealID = DealID; 

    commit; --or check for errors and rollback 
END 
+0

那麼我該怎麼做才能使它工作。 – user960567

+0

我在回答中加入了更多評論。 – danihp

+0

問題在於訂單範圍在每筆交易中是分開的。所以,deal = 1 order = 1,2,3,4 and deal 2 = 1,2,3,4 – user960567