实体完整性

1、定义实体完整性
关系模型的实体完整性在CREATE TABLE中用PRIMARY KEY定义。对单属性构成的码有两种说明方法,一种是定义为列级约束条件,另一种是定义为表级约束条件。对多个属性构成的码只有一种说明方法,即定义为表级约束条件。
【例5.1】将Student表中的Sno属性定义为码

CREATE TABLE Student(Sno CHAR(9) PRIMARY KEY,  /*在列级定义主码*/Sname CHAR(20) NOT NULL,Ssex CHAR(2),Sage SMALLINT,Sdept CHAR(20))

或者

CREATE TABLE Student(Sno CHAR(9),Sname CHAR(20) NOT NULL,Ssex CHAR(2),Sage SMALLINT,Sdept CHAR(20),PRIMARY KEY(Sno)  /*在表级定义主码*/)


【例5.2】将SC表中的Sno、Cno属性组定义为码

CREATE TABLE SC(Sno CHAR(9) NOT NULL,Cno CHAR(4) NOT NULL,Grade SMALLINT,PRIMARY KEY(Sno,Cno) /*只能在表级定义主码*/)

参照完整性

1、定义参照完整性
关系模型的参照完整性在CREATE TABLE中用FOREIGN KEY短语定义哪些列为外码,用REFERENCES短语指明这些外码参照哪些表的主码。
例如,关系SC中一个元组表示一个学生的选修的某门课程的成绩,(Sno,Cno)是主码。Sno,Cno分别参照Student表的主码和Course表的主码
【例5.3】定义SC中的参照完整性
此处用到了Course表,所以我们需要新建一个Course表

CREATE TABLE Course(Cno CHAR(4) NOT NULL,Cname CHAR(40),Ccredit SMALLINT,PRIMARY KEY(Cno), /*在表级定义实体完整性*/)

CREATE TABLE SC(Sno CHAR(9) NOT NULL,Cno CHAR(4) NOT NULL,Grade SMALLINT,PRIMARY KEY(Sno,Cno), /*在表级定义实体完整性*/FOREIGN KEY(Sno) REFERENCES Student(Sno), /*在表级定义参照完整性*/FOREIGN KEY(Cno) REFERENCES Course(Cno))


2、参照完整性检查和违约处理
【例5.4】显式说明参照完整性的违约处理示例

CREATE TABLE SC(Sno CHAR(9) NOT NULL,Cno CHAR(4) NOT NULL,Grade SMALLINT,PRIMARY KEY(Sno,Cno), /*在表级定义实体完整性,Sno、Cno都不为空值*/FOREIGN KEY(Sno) REFERENCES Student(Sno)/*在表级定义参照完整性*/ON DELETE CASCADE  /*当删除Student表中的元组时,级联删除SC表中对应的元组*/ON UPDATE CASCADE, /*当更新Student表中的Sno时,级联更新SC表中的相应元组*/FOREIGN KEY(Cno) REFERENCES Course(Cno)ON DELETE NO ACTION   /*当删除Course表中的元组造成与SC表不一致的时候,拒绝删除*/ON UPDATE CASCADE     /*当更新Course表中的Cno时,级联更新SC表中的相应元组*/)

用户定义完整性

1、属性上的约束条件
在CREATE TABLE中定义属性的同时,可以根据应用要求定义属性上的约束条件,即属性值限制,包括:
列值为非空(NOT NULL)
列值唯一(UNIQUE)
检查列值是否满足一个条件表达式(CHECK短语)
【例5.5】在定义SC表时,说明Sno、Cno、Grade属性不允许为空值

CREATE TABLE SC(Sno CHAR(9) NOT NULL,Cno CHAR(4) NOT NULL,Grade SMALLINT NOT NULL,PRIMARY KEY(Sno,Cno), /*在表级定义实体完整性,Sno、Cno都不为空值*/)

【例5.6】建立部门表DEPT,要求部门名称Dname列值取值唯一,部门编号Deptno列为主码

CREATE TABLE DEPT(Deptno NUMERIC(2),Dname CHAR(9)UNIQUE NOT NULL,Location CHAR(10),PRIMARY KEY(Deptno), /*在表级定义实体完整性,Sno、Cno都不为空值*/)

【例5.7】Student表的Ssex只允许取“男”或“女”

CREATE TABLE Student(Sno CHAR(9) PRIMARY KEY,Sname CHAR(8)NOT NULL,Ssex CHAR(2)CHECK(Ssex IN('男','女')),Sage SMALLINT,Sdept CHAR(20))

检测:

INSERT INTO Student(Sno,Sname,Ssex,Sdept,Sage)
VALUES('201215121','佟陆陆','女','IS',20);
SELECT * FROM Student

INSERT INTO Student(Sno,Sname,Ssex,Sdept,Sage)
VALUES('201215122','佟伊','M','IS',20);
SELECT * FROM Student


报错原因就是在Student表中Ssex有约束条件,输入的内容不符合约束条件所以报错了

【例5.8】SC表的Grade的值应该在0和100之间

CREATE TABLE SC(Sno CHAR(9),Cno CHAR(4),Grade SMALLINT CHECK(Grade>=0 AND Grade<=100),PRIMARY KEY(Sno,Cno),FOREIGN KEY(Sno) REFERENCES Student(Sno),FOREIGN KEY(Cno) REFERENCES Course(Cno),)

2、元组上约束条件的定义
与属性上约束条件的定义类似,在CREATE TABLE语句中可以用CHECK语句定义元组上的约束条件,即元组级的限制,同属性值限制相比,元组级的限制可以设置不同属性之间的取值的相互约束条件
【例5.9】当学生的性别是男的时候,其名字不能以Ms.打头

CREATE TABLE Student(Sno CHAR(9),Sname CHAR(8) NOT NULL,Ssex CHAR(2),Sage SMALLINT,Sdept CHAR(20),PRIMARY KEY(Sno),CHECK(Ssex='女' OR Sname NOT LIKE 'Ms.%'))

完整性约束命名子句

1、完整性约束命名子句
CONSTRAINT<完整性约束条件名><完整性约束条件>
完整性约束条件包括NOT NULL、UNIQUE、PRIMARY KEY、FOREIGN KEY、CHECK短语
【例5.10】建立学生登记表Student,要求学号在90000-99999之间,姓名不能取空值,年龄小于30,性别只能是“男”或“女”

CREATE TABLE Student(Sno NUMERIC(6)CONSTRAINT C1 CHECK(Sno BETWEEN 90000 AND 99999),Sname CHAR(20)CONSTRAINT C2 NOT NULL,Sage NUMERIC(3)CONSTRAINT C3 CHECK(Sage<30),Ssex CHAR(2)CONSTRAINT C4 CHECK(Ssex IN('男','女')),CONSTRAINT StudentKey PRIMARY KEY(Sno))

【例5.11】建立教师表TEACHER,要求每个教师的应发工资不低于3000元。应发工资列Sal与扣除项Deduct之和

CREATE TABLE TEACHER(Eno NUMERIC(4) PRIMARY KEY,Ename CHAR(10),Job CHAR(8),Sal NUMERIC(7,2),Deduct NUMERIC(7,2),Deptno NUMERIC(2),CONSTRAINT TEACHERKey FOREIGN KEY(Deptno)REFERENCES DEPT(Deptno),CONSTRAINT C1 CHECK(Sal+Deduct>=3000))

2、修改表中的完整性限制
可以使用ALTER TABLE语句修改表中的完整性限制
【例5.12】去掉例5.10Student表中对性别的限制

ALTER TABLE StudentDROP CONSTRAINT C4

【例5.13】修改表Student中的约束条件,要求学号在900000-999999之间,年龄由小于30改为小于40

ALTER TABLE StudentDROP CONSTRAINT C1
ALTER TABLE StudentADD CONSTRAINT C1 CHECK(Sno BETWEEN 900000 AND 999999)
ALTER TABLE StudentDROP CONSTRAINT C3
ALTER TABLE StudentADD CONSTRAINT C3 CHECK(Sage<40)

触发器

触发器也叫做事件-条件-动作规则。当特定的系统事件(如对一个表的增、删、改操作,事物的结束等)发生时,对规则的条件进行检查,如果条件成立则执行规则中的动作,否则不执行该动作。规则中的动作体可以很复杂,可以涉及其他表和其他数据库对象,通常是一段SQL存储过程
SQL使用CREATE TRIGGER命令建立触发器,其格式为:
CREATE TRIGGER<触发器名> //每当触发事件发生的时候,该触发器被激活
{BEFORE|AFTER}<触发事件>ON<表名> //指明触发器激活的时间是执行触发事件前或后
REFERENCING NEW|OLD ROW AS<变量> //REFERENCING指出引用的变量
FOR EACH{ROW|STATEMENT} //定义触发器的类型,指明动作体执行的频率
[WHEN<触发条件>]<触发动作体> //仅当触发条件为真时才执行触发动作体
【例5.21】当对表SC的Grade属性进行修改时,若分数增加了10%,则将此次操作记录到另一个表SC_U(Sno,Cno,Oldgrade,Newgrade)中,其中Oldgrade是修改前的分数,Newgrade是修改后的分数
在进行该操作之前还需要对Student表,Course表,SC表添加数据



先定义表SC_U

CREATE TABLE SC_U(Sno CHAR(9) PRIMARY KEY,  /*在列级定义主码*/Cno CHAR(9),Oldgrade SMALLINT,Newgrade SMALLINT)
CREATE TRIGGER SC_T
AFTER UPDATE OF Grade ON SC
REFERENCINGOLDROW AS OldTuple,NEWROW AS NewTuple
FOR EACH ROW
WHEN(NewTuple.Grade>=1.1*OldTuple.Grade)INSERT INTO SC_U(Sno,Cno,OldGrade,NewGrade)VALUES(OldTuple.Sno,OldTuple.Cno,OldTuple.Grade,NewTuple.Grade)

在此处出现报错:“AFTER”附近有语法错误。”
T-SQL的写法与标准SQL的写法是不同的。以下是T-SQL的写法
这时候应该改为

/*新建表SC_U,记录修改的记录*/
CREATE TABLE SC_U(Sno CHAR(9),Cno CHAR(4),Oldgrade SMALLINT,Newgrade SMALLINT
)/*新建触发器SC_T,学生分数增加10%,触发器启动,自动在SC_U里记录信息*/
CREATE TRIGGER SC_T
ON SC
FOR UPDATE
ASdeclare @OLD SMALLINTdeclare @NEW SMALLINTdeclare @SNO CHAR(9)declare @CNO CHAR(4)
IF(UPDATE(Grade))BEGINselect @OLD =Grade FROM DELETEDselect @NEW =Grade FROM INSERTEDselect @SNO =Sno FROM DELETEDselect @CNO =Cno FROM DELETEDIF(@NEW>=1.1*@OLD)INSERT INTO SC_U(Sno,Cno,Oldgrade,Newgrade)VALUES (@SNO,@CNO,@OLD,@NEW)
END

这时当我们修改数据进行检测,第一个数据数据不变,第二个数据增加小于10%,第三个增加大于10%

UPDATE SC
SET Grade=62
WHERE Sno='201215121' AND Cno='2'UPDATE SC
SET Grade=90
WHERE Sno='201215122' AND Cno='1'
SELECT * FROM SCSELECT * FROM SC_U



【例5.22】将每次对表Student的插入操作所增加的学生个数记录到表Student-InsertLog中

/*新建表StudentInsertLog,存储学生人数*/
CREATE TABLE StudentInsertLog(Numbers INT
)/*新建表StudentInsertLogUser存储用户名和操作时间*/
CREATE TABLE StudentInsertLogUser(UserName NCHAR(10),DateAndTime datetime
)
/*新建触发器Student_Count,插入新的学生记录的时候,触发器启动,自动在StudentInsertLog里记录学生的人数*/
CREATE TRIGGER Student_Count
ON Student
AFTER
INSERT
ASINSERT INTO StudentInsertLog(Numbers)SELECT COUNT(*) FROM Student
/*新建触发器Student_Time,当插入新的学生记录时,触发器启动,自动在StudentInsertLogUser记录用户名和操作时间*/
CREATE TRIGGER Student_Time
ON Student
AFTER
INSERT
ASdeclare @UserName nchar(10)declare @DateTime datetimeselect  @UserName=system_userselect  @DateTime=CONVERT(datetime,GETDATE(),120)INSERT INTO StudentInsertLogUser(UserName,DateAndTime)VALUES(@UserName,@DateTime)
/*测试触发器效果*/
INSERT
INTO Student
VALUES('201215122','王超','男',19,'CS')
SELECT * FROM Student
SELECT * FROM StudentInsertLogUser
SELECT * FROM StudentInsertLog



【例5.23】定义一个BEFORE行级触发器,为教师表Teacher定义完整性规则,教授的工资不低于4000元,如果低于4000元,自动改为4000元
首先我们需要先建立一张Teacher表,并且为Teacher表添加数据

/*新建表Teacher,记录教师信息*/
CREATE TABLE Teacher(Tno CHAR(9),Tname CHAR(9),Job CHAR(9),Sal SMALLINT
)
INSERT
INTO Teacher(Tno,Tname,Job,Sal)
VALUES('201201','温宁','讲师',3000)
INSERT
INTO Teacher(Tno,Tname,Job,Sal)
VALUES('201202','焦炎','教授',3000)
INSERT
INTO Teacher(Tno,Tname,Job,Sal)
VALUES('201203','王超','教授',5000)SELECT *
FROM Teacher


标准SQL写法:

/*新建触发器Insert_Or_Update_Sal,教授Sal小于4000就自动改为4000*/
CREATE TRIGGER Insert_Or_Update_Sal
BEFORE INSERT OR UPDATE ON Teacher
REFERENCING NEW row AS newTuple
FOR EACH ROW
BEGINIF(newtuple.Job='教授')AND(newtuple.Sal<4000)THEN newtuple.Sal=4000END IF
END

T-SQL写法:

/*新建触发器Insert_Or_Update_Sal,教授工资低于4000,触发器启动,自动修改为4000*/
CREATE TRIGGER Insert_Or_Update_Sal
ON Teacher
FOR UPDATE,INSERT
ASIF UPDATE(Sal)BEGINdeclare @TNO CHAR(9)declare @TNAME CHAR(9)declare @JOB CHAR(9)declare @SAL SMALLINTselect @SAL = Sal FROM INSERTEDselect @TNO =Tno FROM Teacherselect @TNAME =Tname FROM Teacherselect @JOB =Job FROM TeacherIF(@SAL<4000 AND @JOB='教授')UPDATE TeacherSET SAL=4000WHERE Sal<4000 AND Job='教授'
END

接下来进行测试:

INSERT
INTO Teacher
VALUES('201504','张臣扉','教授',2500)SELECT * FROM Teacher


删除触发器语法:
DROP TRIGGER <触发器名> ON <表名>
【例8.8】利用存储过程实现下面的应用:从账户1转指定数额的款项到账户2中,假设账户关系为Account(Accountnum,Total)

/*建立新表Account,写入两个用户*/
DROP TABLE IF EXISTS Account;
CREATE TABLE Account
(
accountnum INT,
total FLOAT
)INSERT INTO Account VALUES(101,50)
INSERT INTO Account VALUES(102,100)
SELECT * FROM Account

/*建立存储过程*/
IF(exists(select * from sys.objects where name='Proc_TRANSFER'))DROP PROCEDURE Proc_TRANSFER
GO
CREATE PROCEDURE Proc_TRANSFER
@inAccount INT,@outAccount INT,@amount FLOAT
/*定义存储过程TRANSFER,参数为传入账户,转出账户,转账额度*/
AS
BEGIN TRANSACTION TRANSDECLARE /*定义变量*/@totalDepositOut Float,@totalDepositIn Float,@inAccountnum INT;/*检查转出账户的余额*/SELECT @totalDepositOut=total FROM Account WHERE accountnum=@outAccount;/*如果转出账户不存在或者是账户里没有存款*/IF @totalDepositOut IS NULLBEGINPRINT '转出账户不存在或者账户中没有存款'ROLLBACK TRANSACTION TRANS; /*回滚事务*/RETURN;END;/*如果账户存款不足*/IF @totalDepositOut<@amountBEGINPRINT '账户存款不足'ROLLBACK TRANSACTION TRANS; /*回滚事务*/RETURN;END/*检查转入账户的状态*/SELECT @inAccountnum=accountnum FROM Account WHERE accountnum=@inAccount;/*如果转入的账户不存在*/IF @inAccountnum IS NULLBEGINPRINT '转入账户不存在'ROLLBACK TRANSACTION TRANS;RETURN;END;/*如果条件都没有异常,开始转账*/BEGINUPDATE Account SET total =total -@amount WHERE accountnum=@outAccount;/*修改转出账户余额,减去转出额*/UPDATE Account SET total =total +@amount WHERE accountnum=@inAccount;/*修改转入账户余额,加上转出额*/PRINT '转账完成,请取走银行卡'COMMIT TRANSACTION TRANS;RETURN;END

测试:

/*测试,正常情况*/
EXEC    Proc_TRANSFER@inAccount = 101,    --转入账户@outAccount = 102,  --转出账户@amount = 50        --转出金额SELECT * FROM Account

/*测试,余额不足情况*/
EXEC    Proc_TRANSFER@inAccount = 101,    --转入账户@outAccount = 102,  --转出账户@amount = 100       --转出金额

/*测试,转入账户不存在情况*/
EXEC    Proc_TRANSFER@inAccount = 100,    --转入账户@outAccount = 102,  --转出账户@amount = 50        --转出金额

/*测试,转出账户不存在情况*/
EXEC    Proc_TRANSFER@inAccount = 102,    --转入账户@outAccount = 103,  --转出账户@amount = 50        --转出金额

【例8.9】从账户01003815868 转10000元到01003813828账户中

SELECT * FROM AccountINSERT INTO Account VALUES(01003815868,20000)
INSERT INTO Account VALUES(01003813828,10000)
EXEC    Proc_TRANSFER@inAccount = 01003813828,    --转入账户@outAccount = 01003815868,  --转出账户@amount = 10000     --转出金额SELECT * FROM Account

心得:

触发器真的有点麻烦,我终于写完它了(感动(T^T))

【2019-2020春学期】数据库作业13:SQL练习8 - CHECK / CONSTRAINT / TRIGGER / PROCEDURE/ FUNCTION相关推荐

  1. 北师大c语言2019在线作业,华东石油《C语言》2019年春季学期在线作业(二)辅导答案...

    1.C语言2019年春季学期在线作业(二)下列变量的定义及赋值正确的是A.inti=0;j;B.charc=A;C.doublex,y,z;x=y=z=100;D.floata=b=100;正确答案: ...

  2. 奥鹏19春学期c语言作业答案,中石油(华东)《C语言》2013年春学期在线作业(三)...

    <C语言>2013年春学期在线作业(三) g1W奥鹏作业学习网(aopeng123.cn) 试卷总分:100g1W奥鹏作业学习网(aopeng123.cn) 单选题g1W奥鹏作业学习网(a ...

  3. c语言编写重装机兵1,《C语言》2012年春学期在线作业(四).doc

    <C语言>2012年春学期在线作业(四) <C语言>2012年春学期在线作业(四)<C语言>2012年春学期在线作业(四)试卷总分:100 测试时间:-- 试卷得分 ...

  4. 南开大学20春计算机应用基础,南开大学-2020春学期《计算机应用基础》在线作业.txt.pdf...

    20春学期(1709.1803.1809.1903.1909.2003)<计算机应用基础>在线作业 单选题 1.在Excel2003中,电子工作表中的行号为________. A.数字 B ...

  5. 吉大20春学期计算机作业答案,吉大20春学期《文献检索》在线作业二-1(答案)...

    答案来源:奥学网(www.aoxuewang.net)-[吉林大学]吉大20春学期<文献检索>在线作业二 试卷总分:100    得分:100 第1题,<全国报刊索引>创刊于( ...

  6. 奥鹏南开大学18春学期计算机作业,南开18春1709、1803学期《办公自动化基础》在线作业答案.doc...

    [奥鹏][南开大学]18春(1709.1803)学期<办公自动化基础>在线作业 试卷总分:100 得分:100 第1题,"边框和底纹"对话框中的底纹,其设置单位是(). ...

  7. 数据库作业:SQL练习2 - INDEX / INSERT / SELECT

    今天在数据库的课上学习了SQL语句INDEX,INSERT和SELECT,通过例子的练习来加深对他们的理解. 一.INDEX练习 例题: [3.13] CREATE UNIQUE INDEX Stus ...

  8. Dive into Deep Learning加州大学伯克利分校2019年春学期“Introduction to Deep Learning”第一章 Introduction

    Introduction 起源 虽然深度学习似乎是最近几年刚兴起的名词,但它所基于的神经网络模型和用数据编程的核心思想已经被研究了数百年.自古以来,人类就一直渴望能从数据中分析出预知未来的窍门.实际上 ...

  9. 数据库作业:SQL练习1 - CREATE / DROP / ALTER

    1.定义模式:CREATE SCHEMA <模式名>AUTHORIZATION<用户名>; 若没有指定<模式名>,则<模式名>隐含为<用户名> ...

  10. 数据库作业:SQL练习3 - SELECT(单表查询)

    这是一些单表查询的例题的练习. [3.29] SELECT * FROM Student WHERE Sno LIKE '201215121'; 等价于: SELECT * FROM Student ...

最新文章

  1. 53个Python库,你必须要试试
  2. 产品经理也能动手实践的AI(二)- 做个识别宠物的AI
  3. linux 常用命令集
  4. Java并发编程高级篇(十):分离任务的执行和结果的处理
  5. bartender的安全策略不允许指定的用户执行此操作_Linux sudo 被曝提权漏洞,任意用户均能以 root 身份运行命令...
  6. Cannot resolve xxxx(依赖名):unknown
  7. 华为:今年至少 3 亿台设备使用鸿蒙;增长 7%,互联网人薪资报告出炉;英特尔侵犯芯片专利被判赔偿 22 亿美元 | 极客头条...
  8. 阿里的下一个15年:大数据是核心
  9. Zend AMF 相关文章
  10. 线代中最基础的两种玩法
  11. 51. 移除重复脚本(12)
  12. TCP/IP 原理 -- ICMP:因特网控制报文协议
  13. hrbusrt 1900 权限问题
  14. 【密码学基础】02 数论基础
  15. 神奇的分形艺术(一):无限长的曲线可能围住一块有限的面积
  16. 小冰岛——小户赛茶的特点
  17. zblog php 分类页,zblog怎样实现不同分类页调用不同页面模板和样式
  18. Java环境配置 win10教程
  19. badboy录制脚本错误问题解决
  20. Cannot find current proxy: Set ‘exposeProxy‘ property on Advised to ‘true‘ to make it available,and.

热门文章

  1. 使用 AES 对称加密算法对视频文件进行加密解密(C++ 及 Java 实现)
  2. 黑苹果安装 hackintosh Lenovo Y50-70 TransMac 破解版安装
  3. Android JetPack Room
  4. 导出指定layer或指定区域layout的GDS
  5. 智能手环,智能手表,智能眼镜,我们到底该怎么选呢?
  6. ISP(八) Gamma原理详解
  7. C语言之“输出100~200之间的素数”
  8. srand((unsigned int)time(NULL))的理解(C语言)
  9. java 图片去水印_如何用java去除图片水印?
  10. OpenCV把彩色图片转换为灰度图片