利用OBJECT_DEFINITION函數來代碼存檔

做爲一名數據庫管理員,在進行代碼遷移以前,老是盡力給提交於開發環境的代碼一個完整的面貌。可是,不得不認可,我不能保證不發生任何可能破壞開發系統的事情。當這種狀況發生時,可能的補救措施是恢復到目標代碼的前一版本,目標代碼多是存儲過程、函數等等。sql

若是可能的話,你不想作但又不得不作的事情是從備份的數據庫中恢復代碼,可是若是備份的數據庫存儲在磁帶上,這種方法可能因花費太長的時間而不能使用。若是數據庫龐大的話,要花費至關長的時間來恢復,更不用說你還要找一臺足夠大的服務器來存儲備份的文件。不過,還有更好的方法。數據庫

好久前我找到的一種解決方法是備份數據庫代碼到一個獨立的數據表中,這樣若是在咱們開發的代碼發生錯誤時,就能夠從數據表恢復出錯的過程或函數。這種方法確實節省了大量的時間。緩存

在SQL Server 2000中,這種方法能夠這樣實現:對特別的數據庫作一個完整的syscomments數據表備份,而後將備份的數據表放入檔案表中。我一般保存最近兩週的重要過程代碼。利用這種技術惟一的麻煩是:若是代碼對象十分大,那麼可能要對代碼進行重構。由於若是代碼過大將會被存儲到syscomments表中不一樣的行中,有時這多是件使人感到頭痛的事。服務器

SQL Server 2005 新增長的衆多功能之一是能夠利用一個系統函數返回某個對象的完整代碼,這個系統函數將使得存檔你的過程代碼變得十分簡單。app

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函數是如何工做。測試該系統函數的腳本以下:this

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代碼。spa

既然咱們對OBJECT_DEFINITION函數的工做原理有了很好的瞭解,接下來讓咱們看看如何利用這個函數來存檔咱們數據庫中的過程代碼。首先,運行列表A中的腳本程序在測試數據庫中建立20個存儲過程。code

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命令就能很好地完成任務

如今咱們的數據庫中已經有了一些對象,咱們能夠建立用來存檔數據庫中存儲過程須要的對象和代碼。在列表B中的腳本能夠爲咱們完成這項工做。

IF OBJECT_ID('CodeArchive','U')>0     
DROP TABLE CodeArchive
 
CREATE TABLE CodeArchive
(      ArchiveID INT IDENTITY(1,1) PRIMARY KEY,     
ObjectName SYSNAME,     
ObjectDescription VARCHAR(60),     
ObjectType CHAR(2),     
ObjectDefinition VARCHAR(MAX),     
ObjectID INT,     
CreationDate DATETIME,     
ModifiedDate DATETIME,     
EntryDate DATETIME DEFAULT(GETDATE())
)
 
INSERT INTO CodeArchive
( ObjectName, ObjectDescription,
ObjectType, ObjectDefinition,
ObjectID, CreationDate, ModifiedDate
)
SELECT so.name, so.type_desc, so.type,
OBJECT_DEFINITION(object_id),      
so.object_id, so.create_date, so.modify_date   
FROM      sys.objects so
WHERE      so.[type]
IN('C', 'D', 'P', 'FN', 'R', 'RF', 'TR', 'IF', 'TF', 'V')
 

存檔方案首先要求有一個用來存儲咱們定義代碼的表格,和在上面的表格腳本中看到的同樣,咱們將對象定義代碼存入表格的ObjectDefinition域,這是一個VARCHAR(MAX)數據類型的域。VARCHAR(MAX)是SQL Server 2005新增的一種數據類型,它能夠存儲高達2GB的有效數據。這樣咱們就不在侷限於文本數據類型或者將咱們的數據保存在一個單個數據頁上。這種數據類型存儲咱們的對象毫無問題。
在上面的腳本中關於插入CodeArchive表有幾點值得注意的地方。首先是在查詢中包含的數據類型,這些用於OBJECT_DEFINITION函數的對象類型將返回一個值。A列表中包含的。

對象類型列在下面供參考。其次是腳本調用的方法,我一般是利用SQL Server的預約任務調度法執行相似的腳本(你能夠按照工做要求反覆的運行腳本)。不管用什麼調度方法,總之你須要按照必定的規則運行腳本,這樣才能在須要時恢復你的過程代碼。

OBJECT_DEFINITION函數用到的對象類型列表:

T:檢查約束。

D:默認。

P:TSQL存儲過程。

FN:TSQL數值用戶自定義函數。

R:規則。

RF:複製過濾過程。

TR:TSQL觸發器。

IF:TSQL內嵌函數。

TF:TSQL數值函數。

V:視圖。

存檔需求

但願本文對你有所幫助,若是你尚未使用過OBJECT_DEFINITION這個新函數,你最好親自試一下。然而,在你的開發環境中設置一些代碼備份系統,這樣作的重要性在怎麼強調也不爲過。實際上,我擁有一個相似的備份系統用於咱們的開發環境。

若是你能設置一個相似本文提到的恢復系統,就能夠進行本地或遠程備份你的過程代碼,當須要恢復代碼時,你將會很方便地進行,而再也不用查找備份文件已找到所要恢復的代碼。

相關文章
相關標籤/搜索