2012-02-03 95 views
3

我有以下SQL腳本:如何確保在SQL腳本失敗時重置MULTI_USER的登錄權限?

USE MyDatabase 

ALTER DATABASE MyDatabase SET SINGLE_USER WITH ROLLBACK IMMEDIATE 
GO 

BEGIN TRANSACTION 

-- Write to tables here 

COMMIT TRANSACTION 

ALTER DATABASE MyDatabase SET MULTI_USER 
GO 

我想,以確保該腳本運行時我的數據庫不被訪問,這就是爲什麼我在頂部的數據庫設置爲SINGLE_USER

現在,如果事務內部的任何操作失敗(例如語法錯誤),我將永遠不會將數據庫重置回MULTI_USER,這意味着它將永久停留在單用戶模式下(不是我想要的)。

有沒有辦法確保我們總是回到MULTI_USER,哪怕是失敗?

我想我正在尋找相當於一個finally塊在SQL中,但從我讀過的這個不存在。有另一種方法嗎?

值得注意的是,我不能將ALTER DATABASE命令移動到事務中,因爲這是不允許的(因爲它們是立即提交的)。

回答

3

你應該可以使用TRY CATCH來確保你總是回到MULTI_USER

您只需移動命令即可切換回MULTI_USER之後的TRY CATCH塊,因爲FINALLY在SQL Server中不受支持。

我用下面的SQL運行了一個快速測試,它在SQL Server 2005中按預期工作。只要確保ROLLBACK塊中的事務處於CATCH塊中。我使用SELECT 1/0強制代碼進入CATCH塊。出於調試目的,我添加了SELECT user_access_desc ...語句來顯示數據庫確實從單用戶切換回多用戶模式。

USE MyDatabase 

ALTER DATABASE MyDatabase SET SINGLE_USER WITH ROLLBACK IMMEDIATE 
GO 

SELECT user_access_desc from sys.databases WHERE Name = 'MyDatabase' 

DECLARE @errNum AS INT 
DECLARE @errMsg AS VARCHAR(MAX) 
SET @errNum = 0 

BEGIN TRY 

    BEGIN TRANSACTION 
    SELECT 1/0 
    COMMIT TRANSACTION 

END TRY 
BEGIN CATCH 

    SELECT @errNum = ERROR_NUMBER(), @errMsg = ERROR_MESSAGE() 
    ROLLBACK TRANSACTION 

END CATCH 

IF @errNum <> 0 
    SELECT 'An error occurred: ' + CAST(@errNum AS VARCHAR) + '- ' + @errMsg 

ALTER DATABASE MyDatabase SET MULTI_USER 
GO 

SELECT user_access_desc from sys.databases WHERE Name = 'MyDatabase' 

編輯
在我原來的答覆,我有TRY內外的ALTER ... MULTI_USER語句和CATCH塊,但這是不必要的,所以我在TRY CATCH塊之後移動的聲明權。我還添加了一些錯誤報告。這種方法需要注意的一些事情是:

  1. 如果你做任何錯誤處理或報告,你需要確保SQL不會出錯。我可能會將@errNum@errMsg值寫入一個表(包裝在TRY CATCH中),切換回MULTI_USER模式,然後執行任何其他需要的錯誤處理措施,因爲局部變量將在GO之後超出範圍聲明。
  2. 有些錯誤不受TRY CATCH的影響。我鏈接到上面的文件確實列出了這些條件是什麼。
+0

感謝您的好評。這會處理'TRY'塊內的語法錯誤嗎?週一我回到工作崗位時我會試試這個。 – LeopardSkinPillBoxHat 2012-02-04 00:22:07

+0

道歉,我在文檔中看到鏈接到該語法錯誤的文檔沒有處理。 – LeopardSkinPillBoxHat 2012-02-06 03:22:32

+0

是的,看起來不幸的是TRY CATCH不會處理所有的事情,所以如果你使用這種無人值守的腳本(即作爲自動化作業的一部分),你一定要小心。另外,在重讀你的問題之後,由於它不處理語法錯誤,所以這可能不是一個足夠的答案。有一個問題,爲什麼你認爲你會遇到語法錯誤? – rsbarro 2012-02-06 16:30:20