在SQL Server 2005之前,我們只能定義Data Manipulation Language (DML)觸發器。當執行DML語句時,如UPDATE或DALETE,這些觸發器就會啟動。在SQL Server 2005發布之後,現在可以定義Data Definition Language (DDL)觸發器了。當執行DDL語句,如CREATE TABLE和ALTER VIEW,這些類型的觸發器就會啟動,並且這使得使用DDL觸發器來審計SQL Server中的DDL事件更加容易了。
其中一個可以用來審計DDL事件的方法是先創建一個表來存儲相關的事件數據,然後創建一個DDL觸發器來記錄事件。在本文中,我將闡述每個步驟並舉例說明每個概念。對於所舉的例子,我將在傳輸SQL Server 2005的AdventureWorks示例數據庫中創建一個審計表和DDL觸發器。注意,本文的前提條件就是假定你已經非常熟悉Transact- SQL和DDL概念。
創建DDL審計表
審計表存儲每次指定類型的DDL事件發生時產生的事件相關信息。比如,如果從數據庫中刪除一個視圖,那麼就會產生一個DROP_VIEW事件。我們可以使用DDL觸發器來捕捉事件信息並存儲在表中。
每個審計表都必須至少包含一個XML字段來存儲事件相關數據。後面將介紹SQL Server是如何生成XML格式的數據的。當然,這個表也必須包含一個主鍵字段。下面的語句在AdventureWorks數據庫中創建了一個基本的審計表:
CREATE TABLE dbo.EventLog
(EventID INT PRIMARY KEY IDENTITY,
EventInstance XML NOT NULL)
GO
注意,我已經將EventID列作為主鍵,以及EventInstance,並介紹了字段是如何保存與每個事件相關的XML數據的。每次DDL事件生成時,就會有一行添加到表格中。然後,我們可以檢索EventInstance字段的內容來查看指定事件的信息。
創建DDL觸發器
在創建了審計表之後,我們必須定義DDL觸發器。下面的CREATE TRIGGER語句定義了一個觸發器,當每次在AdventureWorks數據庫中發生DDL事件時,它將在EventLog表中插入事件相關的數據:
CREATE TRIGGER LogEvents
ON DATABASE
AFTER DDL_DATABASE_LEVEL_EVENTS
AS
INSERT INTO dbo.EventLog (EventInstance)
VALUES (EVENTDATA())
讓我們詳細地來看看每一行的代碼以便更好的理解它。CREATE TRIGGER子句只是簡單地標識新的觸發器的名稱,也就是LogEvents。第二行——ON DATEBASE——表示觸發器將在數據庫級上創建。當然,也可以在服務器上創建觸發器,它會在服務器發生DDL事件時啟動,這時就應該使用ON ALL SERVER選項。然而,對於這個例子,我們關注的僅僅是與AdventureWorks數據庫相關的DDL事件。
下一行代碼——AFTER DDL_DATABASE_LEVEL_EVENTS——是一個AFTER子句。這個子句的第一部分是一個AFTER關鍵字,它表示只有在相關的操作(特別是子句的第二部分)已經成功的執行了才啟動觸發器。如果不用AFTER,可以用FOR關鍵字,這就意味著一發生DDL事件就啟動事件。因此,我更喜歡在它們成功的運行了之後才記錄這些操作。
AFTER子句的下一個部分指定了事件類型或組。因此你必須規定哪件DDL事件能夠引發觸發器啟動。因為我想要審計數據庫級的所有DDL事件,所以我選擇了DDL_DATABASE_LEVEL_EVENTS選項(一個事件組)。但是,你可以選擇其它的組或某個事件類型。如果指定一個以上的事件組或類型,那麼需要使用逗號分隔選項。更多關於每個事件類型和組的詳細信息,可以閱讀Microsoft SQL Server Books Online上的“CREATE TRIGGER (Transact-SQL)”專欄。
當我指定了事件組之後,我使用了一個AS關鍵字,然後是INSERT語句。這個語句在每次觸發器啟動時插入一行數據到EventLog表中。我通過調用 EVENDATE()系統方法獲得了EventInstance字段的值,它可以檢索事件相關的數據(以XML格式)。當事件發生時,該方法提供所需的值。
這就是設置基本的審計解決方法的所有代碼。現在,讓我們來驗證一下結果。