作為一名數據庫管理員,在進行代碼遷移之前,我總是盡力給提交於開發環境的代碼一個完整的面貌。但是,不得不承認,我不能保證不發生任何可能破壞開發系統的事情。當這種情況發生時,可能的補救措施是恢復到目標代碼的前一版本,目標代碼可能是存儲過程,函數等等。如果可能的話,你不想做但又不得不做的事情是從備份的數據庫中恢復代碼,但是如果備份的數據庫存儲在磁帶上,這種方法可能因花費太長的時間而不能使用。如果數據庫龐大的話,要花費相當長的時間來恢復,更不用說你還要找一台足夠大的服務器來存儲備份的文件。不過,還有更好的方法。
很久前我找到的一種解決方法是備份數據庫代碼到一個獨立的數據表中,這樣如果在我們開發的代碼發生錯誤時,就可以從數據表恢復出錯的過程或函數。這種方法確實節省了大量的時間。
在SQL Server 2000中,這種方法可以這樣實現:對特別的數據庫做一個完整的syscomments數據表備份,然後將備份的數據表放入檔案表中。我通常保存最近兩周的重要過程代碼。利用這種技術唯一的麻煩是:如果代碼對象十分大,那麼可能要對代碼進行重構。因為如果代碼過大將會被存儲到syscomments表中不同的行中,有時這可能是件令人感到頭痛的事。
SQL Server 2005 新增加的眾多功能之一是可以利用一個系統函數返回某個對象的完整代碼,這個系統函數將使得存檔你的過程代碼變得十分簡單。
OBJECT_DEFINITION
SQL Server 2005新增的系統函數OBJECT_DEFINITION根據提供給該函數的對象ID返回對象的TSQL代碼。為了更好的理解這個函數的工作過程,讓我舉個例子。首先我們創建一個用戶自定義函數,該函數的腳本如下:
CREATE FUNCTION udf_Multiply
(@Val1 INT,
@Val2 INT
)
RETURNS INT
AS
BEGIN
DECLARE @RetVal INT
SET @RetVal = (@Val1 * @Val2)
RETURN(@RetVal)
END
這是一個很簡單的小函數。因為它僅僅處理兩個參數,但是已足夠為我們演示OBJECT_DEFINITION函數是如何工作。測試該系統函數的腳本如下:
DECLARE @ObjectID INT
SET @ObjectID = OBJECT_ID('udf_Multiply')
SELECT OBJECT_DEFINITION(@ObjectID)
在這個例子中,我們實際上用了兩個系統函數。首先,我們要得到前面創建的udf_Multiply函數的OBJECT_ID,在SQL Server 數據庫引擎中,OBJECT_ID是一個對象的系統標識符。然後我們將這個ID傳給系統函數OBJECT_DEFINITION,這一系統函數將返回提供給它的ID對象的代碼,即返回值是我們以前為udf_Multiply 函數寫的TSQL代碼。
既然我們對OBJECT_DEFINITION函數的工作原理有了很好的了解,接下來讓我們看看如何利用這個函數來存檔我們數據庫中的過程代碼。首先,運行列表A中的腳本程序在測試數據庫中創建20個存儲過程。
DECLARE @i INT
SET @i = 1
WHILE @i <= 20
BEGIN EXECUTE ( 'IF OBJECT_ID(''usp_TestProcedure'+@i + ''')>0 DROP PROCEDURE usp_TestProcedure'+@i+' ' ) EXECUTE ( ' CREATE PROCEDURE usp_TestProcedure' + @i + ' AS BEGIN PRINT ''The name of this procedure is '' + CAST(OBJECT_NAME(@@PROCID) AS VARCHAR(20)) END' ) SET @i = @i + 1
END你將看到在上面的腳本中,我們使用了動態SQL語句。當創建動態SQl語句時,我習慣用系統存儲過程sp_executesql,因為該過程能夠很好地在系統中緩存SQL語句。但是,在我們這一例子中,EXECUTE命令就能很好地完成任務。