關係性數據庫的完整性是指數據的正確性和相容性,主要是爲了防止數據庫中存在不符合語意的數據。在關係型數據庫中的完整性規則是對關係的某種約束條件,這些約束條件實際上就是現實世界的一些基本的要求。在關係模型中有三種完整性約束:實體完整性,參照完整性和用戶定義的完整性。其中前面兩個:實體完整性和參照完整性是關係模型的必備兩個約束條件,即所謂兩個不變性。用戶定義完整性則是針對某一具體關係數據庫的約束條件,它要求某一關係必須要求所包含數據必須滿足某種語意的要求。
在用戶定義完整性上,觸發器(Trigger)是一種經常被使用的方法。微軟的SQL Server作爲一種關係型數據庫,對於觸發器也有比較全面的功能支持。觸發器是一種特殊類型的存儲過程,他的主要作用就是其能夠實現主鍵和外鍵不能保證的複雜的參照完整性,同時Trigger還可以強化約束,跟蹤變化,級聯運行和存儲過程的調用。在Trigger的類型上SQL Server支持兩種類型的觸發器:AFTER和INSTEDOF。在Trigger的實現方法上SQL Server支持觸發器的遞歸和嵌套。這裏我們主要對Trigger的嵌套和遞歸做實驗測試。
一.SQL Server的嵌套和遞歸
SQL Server可以對使用recursive triggers, nested triggers分別對Trigger的遞歸和嵌套做設置, 根據微軟的相關資料:
RECURSIVE_TRIGGERS:只能限制直接遞歸,不能限制間接遞歸。
Nested_triggers : 允許的嵌套層數最多是32層。
我們這裏主要實驗以下幾個問題:
1. RECURSIVE_TRIGGERS和nested_triggers的的設置方法。
2. RECURSIVE_TRIGGERS和nested_triggers的對於Trigger的影響。
3. Trigger的編寫方法和Trigger的實際效果。
二.SQL Server的嵌套和遞歸的實現
1. RECURSIVE_TRIGGERS 的設置:
其指令如下:
ALTER DATABASE ‘Emp_Struct’ SET RECURSIVE_TRIGGERS OFF(ON);
Recursive triggers: ON: 設置遞歸開啓 ;OFF: 設置遞歸爲關閉
2. Nested triggers 的設置:
其指令如下:
EXEC sp_configure 'nested_triggers', 1(0)
RECONFIGURE WITH OVERRIDE
Nested triggers: 1 : 設置嵌套開啓 ;0 : 設置嵌套關閉
3. 測試數據庫及表格
3.1建立一個測試數據庫:Emp_Struct,
其中包含三個表格: employee, manager, Department
其結構說明如下:
Employee:
欗位 |
Emp_id |
Emp_name |
Depart |
Manager |
Duty |
Report_num |
屬性 |
int |
Char(20) |
Char(20) |
Char(20) |
Char(20) |
int |
說明 |
員工號 |
姓名 |
部門 |
管理人 |
職位 |
下屬人員數 |
manager
欗位 |
Manager_name |
Sec_manager |
depart |
Under_num |
屬性 |
Char(20) |
Char(20) |
Char(20) |
int |
說明 |
主管理人 |
從管理人 |
部門 |
下屬人員數 |
Department:
欗位 |
Depart_name |
Manager_name |
Member_num |
屬性 |
Char(20) |
Char(20) |
int |
說明 |
部門 |
管理人 |
人員總數 |
3.2建立觸發器:
爲了實現觸發器嵌套,我們共設置4個觸發器,
Insert_manager(employee),
Del_manager(employee),
upmanager(manager),
up_depart(depart)
其觸發器嵌套順序如下:
Update
employee |
employee |
Update Manager |
manager |
department |
Update department |
Update employee |
up_manager |
up_depart |
Insert_manager
(Del_manager) |
User Delete (insert) employee |
If Delete(insert) manager |
up_employee |
Update employee |
3.3建立完數據庫和表格以後,插入部分測試數據如下圖:
3.4將遞歸和嵌套參數都設置爲打開狀態
3.4 插入一個名爲TREE職位(duty)爲manager的數據:
在employee表上產生遞歸操作到最大嵌套層32層。數據插入未成功。
3.5 將遞歸選項關閉,保留嵌套。執行數據插入:
三個表格的數據被更新。新manager TREE的資料被插入,原Manager HONG被標記爲sec_manager ,部門人數更新爲7人,報告人數更新爲6人。
3.6 將遞歸選項關閉,保留嵌套。刪除TREE的相關信息。
同時正常出發嵌套的出發器,同時刪除數據成功。
3.7 設置遞歸和嵌套的參數都設置爲OFF,重新插入名字爲TREE的資料
重新插入TREE的資料,數據插入employee但只觸發了第一層的insert_manager觸發器,
故插入的數據未能更新所有相關表格
3.8設置遞歸爲ON和嵌套爲OFF,重新插入TREE數據
爲產生遞歸,僅觸發了第一個觸發器。
以上結果彙總如下:
設置 |
Recursive OFF |
Recursive ON |
Nest OFF |
不可產生遞歸
不可觸發嵌套 |
不可產生遞歸
不可觸發嵌套 |
Nest ON |
不產生遞歸
可觸發嵌套 |
可產生遞歸
可觸發嵌套 |
驗證並得出以下結果:
1. 遞歸和嵌套必須同時設置,遞歸有效纔可用。
2. 遞歸設置只能限制直接遞歸,不能限制間接遞歸。
3. 嵌套的最大層數是32層
4. 無法設置嵌套層數,但在應用中可以通過@@nestlevel判斷嵌套的層數,讓後決定是否執行此Trigger這樣就可以控制trigger的嵌套層數。