關於實現在SQL server中涉及多個表或聚集操作的比較複雜的完整性約束的方法
如果有收穫記得支持,拜謝!
最近學習數據庫系統概論,遇到了一個問題,查了好久沒有解決,請教老師後才瞭解到在SQL server中的斷言(CREATE ASSERTION)要在觸發器中才能實現,即在觸發器中定義涉及多個表或聚集操作的完整性約束,現在分享給大家。
在SQL中可以使用數據定義語言中的CREATE ASSERTION語句,通過聲明性斷言(declarative assertions)來指定更具一般性的約束。可以定義涉及多個表或聚集操作的比較複雜的完整性約束。斷言創建以後,任何對斷言中所涉及關係的操作都會觸發關係數據庫管理系統對斷言的檢查,任何使斷言不爲真值得操作都會被拒絕執行。
——教材原文
在教材中創建斷言的語句格式:
CREATE ASSERTION <斷言名><CHECK子句>
簡單介紹一下,數據庫中有三張表:
- Student(Sno,Sname,Ssex,Sage,Sdept)
- Course(Cno,Cname,Cpno,Ccredit)
- SC(Sno,Cno,Grade)。
下面用一個例題進行演示
例5.18 限制數據庫課程最多60名學生選修。
提示:計算選修數據庫課程的學生人數,需要用到COUNT()。
下面是教材的實現代碼:
CREATE ASSERTION ASSE_SC_DB_NUM
CHECK(60>=(SELECT COUNT(*)
FROM Course,SC WHERE SC.Cno=Course.Cno AND Course.Cname=’數據庫’)
);
上面的代碼是標準SQL中的語句格式,可以實現涉及多個表或聚集操作的斷言。但在不同的平臺有不同的語句格式。
那麼,在SQL中是這樣的嗎?可以正常運行嗎?
當然,,,不是&&不行!
在SQL server中沒有ASSERTION這一關鍵字。那麼怎麼才能實現涉及多個表或聚集操作的斷言呢?
是這樣的,在SQL server中使用觸發器才能實現以上的情況。
SQL server中觸發器創建的格式是:
CREATE TRIGGER <觸發器名> ON <表名> FOR <觸發事件> AS <觸發動作體>
觸發器名和表名不作解釋了,相信大家都懂得。
觸發事件可以是INSERT、DELETE或UPDATE,也可以是幾個事件的組合。
觸發動作體可以簡單理解爲觸發條件爲真時進行的動作,執行的SQL塊。
創建
下面就是在SQL server中用觸發器實現SQL斷言的代碼:
--創建insert插入類型觸發器
IF (OBJECT_ID('TGR_SC_INSERT', 'TR') IS NOT NULL) -- 如果已經存在該觸發器,就刪除
DROP TRIGGER TGR_SC_INSERT
GO
CREATE TRIGGER TGR_SC_INSERT
ON SC
FOR INSERT --插入觸發
AS
-- 定義變量,DECLARE聲明(declare)
-- @COUNT存儲已經選擇數據庫課程的學生數量;@Sno學號;@Cno課程號;@Grade課程成績
DECLARE @COUNT INT,@Sno CHAR(9),@Cno CHAR(4), @Grade SMALLINT;
-- 查詢已經選擇“數據庫”課程的學生的數量,並賦值給@COUNT
SELECT @COUNT=COUNT(*) FROM Course,SC WHERE SC.Cno=Course.Cno AND Course.Cname='數據庫';
-- 在INSERTED中查詢已經插入的記錄信息,即觸發觸發器的INSERT語句所插入的記錄信息
SELECT @Sno=Sno,@Cno=Cno,@Grade=Grade FROM INSERTED; -- inserted
IF(@COUNT>3) -- 在插入語句後,如果選修“數據庫”課程的學生數量超過三人,就刪除插入的信息
BEGIN
DELETE SC WHERE Sno=@Sno AND Cno=@Cno AND Grade=@Grade;
END
GO
由於SQL server中沒有BEFORE關鍵字,該觸發器是在插入後進行判斷,如果不符合約束再刪除,符合約束則保留。
驗證
- 先刪除選修了數據庫課程的記錄(表中Cno=‘1’,Cname=‘數據庫’)
DELETE SC WHERE Cno='1';
結果集:
2. 再插入數據4條記錄
INSERT INTO SC VALUES ('201215121','1',59);
INSERT INTO SC VALUES ('201215122','1',92);
INSERT INTO SC VALUES ('201215123','1',90);
INSERT INTO SC VALUES ('201215125','1',80);
執行消息:
執行結果是5行受影響,原因是第4條語句執行後不符合約束條件,插入後再次刪除(3+2=5次)。
- 查詢SC表
SELECT * FROM SC WHERE Cno='1';
SELECT COUNT(*) FROM SC WHERE Cno='1';
結果集:
持續更新
更新:兩個臨時表deleted和inserted,起到了標準SQL中的before和after關鍵字的作用。——2020年5月16日09:50:05
下面是一位博友的詳細介紹,表格看起來挺形象的。