关于实现在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
下面是一位博友的详细介绍,表格看起来挺形象的。