2009-02-24 34 views
1

我是一個很長時間的Firebird用戶,它有一個稱爲Generators的特性(我認爲Oracle也有它,它被稱爲Sequences)。我是SQL Server的新手,我需要模擬相同的功能。我無法使用身份字段來解決我的問題。我需要一系列命名值,而不是每行的唯一編號。對錶格執行可序列化更新的最佳方法

我最擔心的是不止一個用戶同時調用該過程並獲得重複值,因此我決定使用SERIALIZABLE隔離級別進行鎖定。

所以我想出了這個代碼(我使用SQL Server 2005):

CREATE TABLE dbo.GENERATORS 
    (
     [NAME] VARCHAR(30) NOT NULL, 
     [VALUE] INT, 
     CONSTRAINT UNQ_GENERATORS_NAME UNIQUE NONCLUSTERED ([NAME]) 
    ) 
GO 

CREATE PROCEDURE GEN_ID 
    (
     @GENERATOR_NAME VARCHAR(30) 
    ) 
AS 
    DECLARE @RETURN_VALUE INT ; 
    SET NOCOUNT ON 
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE 
    BEGIN TRANSACTION 
    UPDATE GENERATORS 
    SET  [VALUE] = [VALUE] + 1 
    WHERE [NAME] = @GENERATOR_NAME 
    IF @@ROWCOUNT = 0 
     BEGIN 
      INSERT INTO dbo.GENERATORS ([NAME], [VALUE]) 
      VALUES (@GENERATOR_NAME, 1) 
      SET @RETURN_VALUE = 1 
     END 
    ELSE 
     BEGIN 
      SELECT @RETURN_VALUE = [VALUE] 
      FROM GENERATORS 
      WHERE [NAME] = @GENERATOR_NAME 
     END 
    COMMIT TRANSACTION 
    RETURN @RETURN_VALUE 
GO 

所以我的問題是:

  • 這是一個很好的解決方案嗎?
  • 有沒有更好的辦法?

謝謝。

回答

2

相反UPDATE和SELECT中,得到值回您剛纔添加的,你可以做

UPDATE GENERATORS 
SET  @RETURN_VALUE = [VALUE] = [VALUE] + 1 
WHERE [NAME] = @GENERATOR_NAME 

可以去除隔離級別的需求

我寧願回到@RETURN_VALUE爲一個OUTPUT參數,而不是一個返回值 - 在執行過程中任何錯誤代碼的返回值都是空閒的。

+0

這是非常好的,非常感謝。 – 2009-02-24 16:57:33