📖 前言:随着计算机的普及,数据库的使用也越来越广泛。为了适应和满足数据共享的环境和要求,DBMS要对数据库进行保护,保证整个系统的正常运转,防止数据意外丢失、被窃取和不一致数据产生,以及当数据库遭受破坏后能迅速地恢复正常。通常DBMS对数据库的保护是从安全性控制、完整性控制﹑并发控制和数据库的备份与恢复等四个方面实现的,本章主要讲述的是数据库的安全性和完整性控制。
目录
🕒 0. 思维导图
🕒 1. 相关概念
数据库的数据保护主要包括数据库的安全性和完整性保护机制。
问题的提出
-
数据库的一大特点是数据可以共享,数据共享必然带来数据库的安全性问题
-
数据库系统中的数据共享不能是无条件的共享
例: 军事秘密、国家机密、新产品实验数据、市场需求分析、疫情流调数据等 -
数据库中数据的共享是在DBMS统一的严格的控制之下的共享,即只允许有合法使用权限的用户访问允许他存取的数据(举例:数据库的老师不能修改其他课程的成绩)
-
数据库系统的安全保护措施是否有效是数据库系统主要的性能指标之一
安全性概念:
- 数据库的安全性是指保护数据库,防止因用户非法使用数据库造成数据泄露、更改或破坏,从而确保数据库中数据的安全。
- 目的:保护数据库防止恶意的破坏和用户非法的存取
- 防范对象:非法用户和非法操作
完整性概念:
- 数据的正确性和相容性
- 是数据库的一个重要特征,也是保证数据库中的数据切实有效、防止错误、实现商业规则的一种重要机制。
- 目的:防止数据库中存在不符合语义的数据,也就是防止数据库中存在不正确的数据
- 防范对象:不合语义的、不正确的数据
为维护数据库的完整性,DBMS必须:
- 提供定义完整性约束条件的机制
- 提供完整性检查的方法
- 违约处理(如拒绝访问)
🕒 2. 数据库安全性的含义
- 安全性问题是计算机系统中普遍存在的一个问题,而在数据库系统中显得尤为突出。
- 原因:数据库系统中大量数据集中存放,而且为许多最终用户直接共享。数据库系统建立在操作系统之上,而操作系统是计算机系统的核心,因此数据库系统的安全性与计算机系统的安全性息息相关。
在一般计算机系统中,安全措施是一层一层设置的,下图是常见的计算机系统安全模型。
🕒 3. 安全性控制的一般方法
🕘 3.1 用户标识和鉴别(Identification & Authentication)
- 系统提供的最外层安全保护措施
- 当用户进入数据库系统时,需要提供用户的标识,系统根据标识鉴别此用户是不是合法用户:
- 对于合法的用户,进一步开放数据库的访问权限;
- 对于非法用户,则拒绝该用户对数据库进行存取操作。
常用方法:
- 输入用户标识(由用户名(user name)和用户标识号(UID)两部分组成)合法身份
- 回答用户口令(即密码)标识身份
- 通过回答随机数的运算结果标识合法身份
- 通过个人特征鉴别标识合法身份(如指纹、人脸)
🕘 3.2 存取控制 ☆☆☆
数据库安全性所关心的主要是DBMS的存取控制机制。存取控制是确保具有授权资格的用户访问数据库的权限,同时使得所有未被授权的人员无法访问数据库的机制。
🕤 3.2.1 用户分类与权限
对于一个数据库,不同的用户有不同的访问要求和使用权限。
一般可以将数据库的用户分为四类:
- 系统用户(DBA)
- 数据库对象的属主(Owner)
- 一般数据库用户
- 公共用户(public)
系统用户(DBA)
- 拥有支配整个数据库资源的特权,对数据库拥有最高的特权,因而也对数据库负有特别的责任。DBA特权命令包括给各个独立的帐户、用户或者用户组授予特权和回收特权,以及把某个适当的安全分类级别指派给某个用户帐户。
数据库对象的属主
- 是数据库的创建者,他除了一般数据库用户拥有的权力外,还可以授予或收回其他用户对其所创建的数据库对象的存取权。
一般数据库用户
- 就是通过授权可对数据库进行操作的用户。
公共用户
- 是为了方便共享数据操作而设置的,它代表全体数据库用户,如果把某个数据对象的某项操作授权给公共用户,则一个合法的数据库用户都能进行该项数据操作。
🕤 3.2.2 存取控制机制的组成
定义用户权限:用户权限是指用户对于数据对象能够执行的操作种类。进行用户权限定义,系统必须提供有关用户定义权限的语言。
合法权限检查:每当用户发出存取数据库的操作请求后,DBMS首先查找数据字典,进行合法权限检查,如果用户的操作请求没有超出其数据操作权限,则准予执行其数据操作;否则,拒绝其执行此操作。
用户权限定义和合法权限机制一起组成了 DBMS 的安全子系统。
🕤 3.2.3 存取机制的类别
自主存取控制☆(Discretionary Access Control ,简称DAC):
- 用户对于不同的对象有不同的存取权限;
- 不同的用户对同一对象的存取权限也不同;
- 用户也可以将自己拥有的权限传授给其他用户。
- 特点:灵活
强制存取控制(Mandatory Access Control,简称 MAC):
- 每一个数据对象被标以一定的密级(比如一个特务只知道他的上下线,而不知道更多);
- 每一个用户也被授予某个级别的访问许可证;
- 对于任意一个对象,只有具有合法许可证的用户才可以存取。
- 特点:严格
🕘 3.3 视图机制
把要保密的数据对无权存取这些数据的用户隐藏起来,对数据提供一定程度的安全保护
- 主要功能是提供数据独立性
- 间接实现了支持存取谓词的用户权限定义
例1:允许一个用户查询学生表Student的记录,但是只允许他查询“计算机科学与技术”专业学生的情况。
CREATE VIEW Student_SUBJECT
AS SELECT Sno, Sname, Ssex, Sage, Smajor
FROM Student
WHERE Smajor='计算机科学与技术'
使用视图Student_SUBJECT的用户看到的只是基本表Student的一个“水平子集”,或称行子集。
🕘 3.4 数据加密
定义:防止数据库中数据在存储和传输中失密的有效手段
加密的基本思想
- 根据一定的算法将原始数据(明文)变换成不可直接识别的格式(密文)
加密方法
- 代替方法:该方法使用密钥将明文中的每一个字符转换为密文中的字符。
- 置换方法:该方法仅将明文的字符按不同的顺序重新排列。
- 混合方法:如数据加密标准DES
DBMS中的数据加密(可选的)
🕘 3.5 跟踪审计
跟踪审计(Audit Trial)是一种监视措施,数据库运行中,DBMS跟踪用户对一些敏感数据的存取活动,把用户对数据库的操作自动记录下来放入审计日志(Audit Log)中,有许多DBMS的跟踪审计记录文件与系统的运行日志合在一起。系统能利用这些审计跟踪的信息,重现导致数据库现状的一系列事件。
- 审计日志
- 将用户对数据库的所有操作记录在上面
- DBA 利用审计日志
- 找出非法存取数据的人、时间和内容
- C2以上安全级别的DBMS必须具有
安全级别 定 义 A1 验证设计 (Verified Design) B3 安全域(Security Domains) B2 结构化保护 (Structural Protection) B1 标记安全保护 (Labeled Security Protection) C2 受控的存取保护 (Controlled Access Protection) C1 自主安全保护 (Discretionary Security Protection) D 最小保护 (Minimal Protection) \begin{array}{|l|l|} \hline \text { 安全级别 } & {\text { 定 义 }} \\ \hline \text { A1 } & \text { 验证设计 (Verified Design) } \\ \hline \text { B3 } & \text { 安全域(Security Domains) } \\ \hline \text { B2 } & \text { 结构化保护 (Structural Protection) } \\ \hline \text { B1 } & \text { 标记安全保护 (Labeled Security Protection) } \\ \hline \text { C2 } & \text { 受控的存取保护 (Controlled Access Protection) } \\ \hline \text { C1 } & \text { 自主安全保护 (Discretionary Security Protection) } \\ \hline \text { D } & \text { 最小保护 (Minimal Protection) } \\ \hline \end{array} 安全级别 A1 B3 B2 B1 C2 C1 D 定 义 验证设计 (Verified Design) 安全域(Security Domains) 结构化保护 (Structural Protection) 标记安全保护 (Labeled Security Protection) 受控的存取保护 (Controlled Access Protection) 自主安全保护 (Discretionary Security Protection) 最小保护 (Minimal Protection)
跟踪审计的记录一般包括以下内容:
- 请求(源文本)
- 操作类型(如修改、查询等)
- 操作终端标识与操作者标识
- 操作日期和时间
- 操作所涉及的对象(表、视图、记录、属性等)
- 数据的前映象和后映象
DBMS提供相应的语句供施加和撤销跟踪审计之用
🕘 3.6 统计数据库的安全
统计数据库
- 允许用户查询聚集类型的信息(如合计、平均值等)
- 不允许查询单个记录信息
统计数据库中特殊的安全性问题
- 隐蔽的信息通道
- 能从合法的查询中推导出不合法的信息
推断控制方法:
- 数据扰动
- 查询控制
- 历史相关控制
统计数据库的安全问题尚未彻底解决。
🕒 4. SQL Server2014的数据库安全性控制
🕘 4.1 身份验证模式
SQL Server支持两类登录名:
- Windows授权用户
- SQL Server授权用户
SQL Server 2014相应地提供了两种身份验证模式:
- Windows身份验证模式(只支持Windows授权用户)
- 混合验证模式(两类都支持)
在SSMS(SQL Server Management Studio 是用于管理SQL Server基础架构的集成环境)中设置身份验证模式
重启SQL Server 的正确方法
有时更改一些操作,提示需要重启SQL Server ,可不是直接关掉再打开,而是如下。
方法①:SQL配置管理器
方法②:控制面板
控制面板->管理工具->服务->找到你的服务器
🕘 4.2 登录名
对于SQL Server数据库服务器,支持两种类型的登录名:
- Windows用户
- SQL Server授权用户;
建立这两种登录名也是用两种方法:
- 通过SQL Server自身的SSMS工具完成
- 通过T-SQL语句实现
建立登录名的实现方法:
- 用SSMS工具建立Windows身份验证的登录帐户
- 用SSMS工具建立SQL Server身份验证的登录帐户
- 用T-SQL语句建立登录帐户
CREATE LOGIN login-name
- 登录名的删除
DROP LOGIN login-name
🕘 4.3 数据库用户
数据库用户一般来自于服务器上已有的登录账户,让登录账户成为数据库用户的操作称为“映射”。一个登录名可以被授权访问多个数据库,但一个登录名在每个数据库中只能映射一次,即一个登录名可对应多个用户,一个用户也可以被多个登录名使用。可以简单的把SQL Server想象成一栋大楼,里面的每个房间都是一个数据库,登录名只是进入大楼的钥匙,而用户名则是进入房间的钥匙,一个登录名可以有多个房间的钥匙,但一个登录名在一个房间只能拥有此房间的一把钥匙。管理数据库用户的过程实际上就是建立登录名与数据库用户之间的映射关系的过程。
数据库用户首先必须是一个有效的登录账户
建立数据库用户的方法
- 用SSMS工具建立数据库用户
- 用T-SQL语句建立数据库用户
CREATE USER user_name [{FOR | FROM}]
{
LOGIN login_name
}
例2:让SQL_U2登录名成为教学管理信息系统数据库中的用户,且用户名和登录名相同。
USE 教学管理信息系统
CREATE USER SQL_U2;
如果只是创建了一个用户,而没有映射数据库的话,那么仅能访问系统数据库。但无法访问自定义表
❗ 转载请注明出处
作者:HinsCoder
博客链接:🔎 作者博客主页
数据库用户的删除
DROP USER user_name
🕘 4.4 角色
- 在SQL Server数据库中,可以将一组具有相同权限的用户组织在一起,这一组具有相同权限的用户称为角色。也可以将角色理解为一组权限的集合。
- 角色类似于Windows账户管理中的一个用户组,可以包含多个用户。
- 在实际工作中,把具有相同权限的用户集中在角色中进行管理,将会大大减少管理员的工作量。
- 对于角色的权限管理,可以为有相同权限的一类用户建立一个角色,然后为角色授予合适的权限,当有人要具有相同的权限时,只需要将角色的权限授予该用户即可,而若要回收该用户的权限,则将其从该角色中删除即可。
角色分类:
- 固定的服务器角色
- 固定的数据库角色
- 用户定义的角色☆
- 应用程序角色
- 用户定义的角色属于数据库级别的角色,有了角色的使用,DBA无需直接管理每个具体的数据库用户的权限,而是将用户分成不同的组,每个组具有相同的操作权限,这些具有相同权限的组在数据库中被称为用户定义的角色。
- 数据库管理员在管理用户时,只需要将数据库用户放到合适的角色即可,当组的职能发生变化时,只需要更改角色的权限,而不需要关心角色中的成员。用户定义的角色成员可以是数据库中的用户,也可以是用户定义的角色。
创建用户定义角色方法
方法一:通过SSMS工具
方法二:通过T-SQL语句
CREATE ROLE role_name [ AUTHORIZATION owner_name ]
注意:sp_addrole、sp_addrolememeber等的使用
同理, 删除角色成员使用的存储过程也是sp_droprolememeber,而删除角色所使用的T-SQL语句为DROP ROLE。
例3:在教学管理信息系统数据库中创建用户定义的角色accounting,并指定dbo为该角色所有者,并为该角色添加用户Jack(假定该用户已存在)。
USE 教学管理信息系统
GO
CREATE ROLE accounting AUTHORIZATION dbo
GO
EXEC sp_addrolemember ‘accounting’, ‘Jack’
例4:删除数据库角色accounting。
USE 教学管理信息系统
GO
EXEC sp_droprolemember 'accounting', 'Jack' /*先删角色成员*/
GO
DROP ROLE accounting
注意:
- 除了将用户添加成为角色的成员,也可以将角色添加成为另外一个角色的成员。
- 无法从数据库删除拥有安全对象的角色。若要删除拥有安全对象的数据库角色,必须首先转移这些安全对象的所有权,或从数据库删除它们。
- 无法从数据库删除拥有成员的角色。若要删除有成员的角色,必须首先删除角色的成员。
- 不能使用
DROP ROLE
删除固定数据库角色。
🕘 4.5 权限管理
用户使用数据库的方式称为权限。使用数据库的权限分为二类:
-
访问数据特权:
- 读数据权限、插入数据权限、修改数据权限和删除数据权限。
-
修改数据库模式的特权:
- 创建和删除索引的索引权限,创建新表的资源权限,允许修改表结构的修改权限,允许撤销关系表的撤销权限等。
在SSMS中:
- 授予权限:授予用户或角色具有某种操作权。
- 回收权限:收回(或撤销)曾经授予用户或角色的权限。
- 拒绝权限:拒绝某用户或角色具有某种操作权限。一旦拒绝了用户的某个操作权限,则用户从任何地方都不能获得该权限。
方法一:用SSMS工具实现对权限的管理
(1)授予数据库的权限(修改数据库模式特权)
(2)授予数据库对象上的权限(访问数据库特权)
方法二:用T-SQL语句实现对权限的管理
🕤 4.5.1 授予权限
GRANT {ALL[PRIVILEGES]} ︱权限 [(列 [ , …])] [,…]
[ON 〈数据对象〉] TO〈被授权者〉
[WITH GRANT OPTION] [AS 主体]
- 注意:使用GRANT语句时有两个特殊的用户和角色,即public角色和guest用户。public是一个特殊的保留字,代表该数据库系统的全体用户。对于大部分可以公开的数据,可以一次性地授权给public,而不必对每个用户逐个授权。授予guest用户的权限可为所有在数据库中没有数据库用户账户的访客使用。
例5:在教学管理信息系统数据库中,将表Student的SELECT、DELETE操作权限授予所有的用户。
GRANT SELECT,DELETE ON Student TO PUBLIC;
例6:将表Student的学号、姓名字段的UPDATE权限授予给zhao。
GRANT UPDATE(Sno,Sname)ON Student TO zhao;
例7:将表Student中姓名和年龄的INSERT特权授予zhang,并允许他将此特权转授给其他用户。
GRANT INSERT(Sname,Sage)ON Student TO zhang WITH GRANT OPTION;
例8:【权限综合练习】☆☆☆
假设有用户Jean、Jill和Jack和角色Accounting,用户Jean拥有表Plan_Data(有权限)。逐步进行如下操作:
① 首先创建角色Accounting,并将用户Jill添加成为Accounting的成员。
② Jean将表Plan_Data的 SELECT 权限授予Accounting角色,并允许其成员转授。
③ 用户Jill将表Plan_Data上的SELECT权限授予用户Jack,Jack不是Accounting的成员。
分析:因为对表Plan_Data的SELECT以及转授的权限,是授予Accounting角色而不是显式地授予Jill,所以不能因为已授予 Accounting 角色中成员该权限,而使Jill能够将该权限转授,Jill 必须用 AS 子句来获得 Accounting 角色的转授权限。
实操:
我们首先创建登录名Jill
如上则创建好登录名及用户Jean、Jill和Jack。
/* DBA身份执行 */
CREATE ROLE Accounting;
EXEC sp_addrolemember 'Accounting', 'Jill'; /*第1题*/
/* User Jean 身份执行*/
CREATE TABLE Plan_data /*创建一个测试用的表(完成题目要求)*/
( id char(2) PRIMARY KEY,
name char(8)
)
GRANT SELECT ON Plan_Data TO Accounting WITH GRANT OPTION /*第2题*/
/* User Jill 身份执行 */
GRANT SELECT ON Plan_Data TO Jack AS Accounting /*第3题*/
🕤 4.5.2 拒绝权限
DENY {ALL[PRIVILEGES]} ︱权限 [(列 [ , …])] [,…]
[ON 〈数据对象〉] TO〈受权者〉
[CASCADE] [AS 主体]
例9:对于用户zhao和zhang,不允许其创建表和视图。
DENY CREATE VIEW,CREATE TABLE TO zhao,zhang;
例10:对于用户li,wang,拒绝其对Course表的增删改的权限。
DENY INSERT,UPDATE,DELETE on Course to li,wang;
例11:对于角色R1的所有角色成员拒绝CREATE RULE权限。
DENY CREATE RULE TO R1;
注意:假设有用户huang是R1的成员,即使显示授予了CREATE RULE
权限,仍会拒绝huang的CREATE RULE
权限。
🕤 4.5.3 回收权限
当用户将某些权限授给其他用户后,有时还需要把权限收回,回收权限需要使用REVOKE语句。格式如下:
REVOKE [GRANT OPTION FOR]
{ALL[PRIVILEGES]} ︱权限 [(列 [ , …])] [,…]
[ON 〈数据对象〉] TO︱FROM〈受权者〉
[CASCADE] [AS 主体]
例12:收回已授予liu的CREATE TABLE权限。
REVOKE CREATE TABLE FROM liu;
例13:取消以前对zhang用户授予或拒绝的在Student表中姓名和年龄的INSERT特权。
REVOKE INSERT(Sname,Sage)ON Student FROM zhang;
🕘 4.6 数据库架构的定义和使用(了解)
- 在SQL Server 2014中,数据库架构(Schema)是一组数据库对象的集合,它被单个负责人(可以是用户或角色)所拥有并构成唯一命名空间。可以将架构看成是对象的容器,数据库中的对象都属于某一个架构,架构的所有者可以访问架构中的对象,并且还可以授予其他用户访问该架构的权限。
- 架构在数据库中跟角色和用户并列存在,对于架构的创建也同样有两种方式,可以通过SSMS实现,也可以通过T-SQL中CREATE SCHEMA语句实现。
🕒 5. 数据库完整性的含义
- 数据库的完整性是指保护数据库中数据的正确性、有效性和相容性,即为了防止数据库中存在不符合语义的数据,防止错误信息的输入和输出。
- 例如,学生的年龄是整数,取值范围应为14~45;月份只能是1~12之间的正整数;一个人不能有两个身份证号;学生学的专业必须是学校已有的专业等。
- 数据库的完整性保证了真实反映现实世界,凡是已经失真的数据都可以说其完整性受到了破坏,这种情况下就不能再使用数据库,否则可能造成严重的后果。
完整性受破坏的常见原因:
- 错误的数据
- 错误的更新操作
- 并发访问
- 各种硬件故障
- 人为的破坏
🕒 6. 数据库的完整性控制
🕘 6.1 DBMS对完整性的支持
-
为了维护数据库的完整性,数据库管理系统必须提供对完整性约束的支持。
-
完整性规则是数据库中数据必须满足的语义约束条件,所表达的是给定数据模型中数据以及数据之间联系所具有的制约与依存规则,用以保证数据库状态发生改变时,其数据的正确性、有效性和相容性。在关系模型中,其完整性主要包括实体完整性、参照完整性以及用户自定义的完整性。
-
SQL标准使用了一系列的概念来描述其完整性;实体完整性一般通过
PRIMARY KEY
关键字实现,参照完整性一般通过FOREIGN KEY……REFERNCES
来实现,而用户自定义的完整性一般可以通过NOT NULL
约束、UNIQUE
约束、CHECK
约束、规则RULE和触发器实现。 -
对于完整性约束,当对数据库执行
INSERT
、UPDATE
和DELETE
语句时,数据库管理系统必须提供一定的机制进行检查,检查这些操作执行后是否会破坏数据库的完整性约束。数据库管理系统若发现有用户进行了违背完整性约束的操作,必须提供一定的处理方法,比如拒绝操作、级联操作等,以保证数据库的完整性,不需要用户编程实现这些语义的约束。
🕘 6.2 实体完整性
-
CREATE TABLE
中用PRIMARY KEY
定义 -
一个表只能有一个PRIMARY KEY约束
-
PRIMARY KEY约束可以由几个属性列组成
- 某一列的值可以重复,但组合值必须唯一
-
当为表定义PRIMARY KEY约束时,SQL为主键创建唯一索引,实现主键数据的唯一性,在查询中,该索引可用来对数据进行快速访问。
-
用PRIMARY KEY约束定义了关系的主码后,每当用户程序对主码列进行更新操作时,系统自动进行完整性检查,凡操作使主码值为空值或使主码值在表中不唯一,系统拒绝此操作,从而保证了实体完整性。
插入或对主码列进行更新操作时,RDBMS按照实体完整性规则自动进行检查。包括:
- 检查主码值是否唯一,如果不唯一则拒绝插入或修改
- 检查主码的各个属性是否为空,只要有一个为空就拒绝插入或修改
检查记录中主码值是否唯一可以进行全表扫描,即扫描表中每一条记录的主码值与将插入记录或将修改的新主码值进行比较,判断二者是否相同,但全表扫描是十分耗时的,因此,关系数据库管理系统一般会在所创建的主键上自动建立索引,从而大大提高检查的效率。
🕘 6.3 参照完整性
- 在
CREATE TABLE
中用FOREIGN KEY
短语定义哪些列为外码
用REFERENCES
短语指明这些外码参照哪些表的主码
在SQL中,有两种方法用于说明一个外部关键字:
- 第一种方法:
可以在它的属性名和类型后面直接用“REFERENCES”说明它参照了某个被参照表的某些属性(必须是主关键字),其格式为:
REFERENCES <表名>(<属性>)
- 另一种方法:
在CREATE TABLE语句的属性列表后面增加一个或几个外部关键字说明,其格式为:
FOREIGN KEY <属性> REFERENCES <表名>(<属性>)
例14:在教学管理信息系统中,创建选课表SC时,除了将Sno和Cno属性组合设置为外码,同时设置Sno与Cno为SC表的外键,其取值分别参照引用Student表的主码和Course表的主码,则有:
CREATE TABLE SC
(Sno CHAR(8) REFERENCES Student(Sno), /*外码定义在列级*/
Cno CHAR(4),
Grade SMALLINT,
PRIMARY KEY(Sno,Cno), /*主码只能定义在表级*/
FOREIGN KEY (Cno) REFERENCES Course(Cno) /*外码定义在表级*/
);
参照完整性检查和违约处理
可能破坏参照完整性的情况及违约处理
被参照表(如Student) 参照表(如SC) 违约处理 可能破坏参照完整性← ←插入元组 拒绝 可能破坏参照完整性← ←修改外码值 拒绝 删除元组→ →可能破坏参照完整性 拒绝/级联删除/设置为空值 修改主码值→ →可能破坏参照完整性 拒绝/级联删除/设置为空值 \begin{array}{|l|l|l|} \hline \text { 被参照表(如Student) } & \text { 参照表(如SC)} & \text { 违约处理} \\ \hline \text { 可能破坏参照完整性← } & \text { ←插入元组 } & \text { 拒绝 } \\ \hline \text { 可能破坏参照完整性← } & \text { ←修改外码值 } & \text { 拒绝 } \\ \hline \text { 删除元组→ } & \text { →可能破坏参照完整性 } & \text { 拒绝/级联删除/设置为空值 } \\ \hline \text { 修改主码值→ } & \text { →可能破坏参照完整性 } & \text { 拒绝/级联删除/设置为空值 } \\ \hline \end{array} 被参照表(如Student) 可能破坏参照完整性← 可能破坏参照完整性← 删除元组→ 修改主码值→ 参照表(如SC) ←插入元组 ←修改外码值 →可能破坏参照完整性 →可能破坏参照完整性 违约处理 拒绝 拒绝 拒绝/级联删除/设置为空值 拒绝/级联删除/设置为空值
举例:在Student表中删除学号为“20211025”的学生,由于该学生在SC表有选课记录,可能破坏参照完整性,因此违约处理有拒绝/级联删除(即把两个表的相关记录都删了)/设置为空值(一般不会)
违约处理:
- 拒绝(NO ACTION)执行 (默认策略)
- 级联(CASCADE)操作
- 设置为空值(SET-NULL)
对于参照完整性,除了应该定义外码,还应定义外码列是否允许空值
例15:在例14中,创建选课表SC,将Sno和Cno属性组合设置为主码,设置Sno与Cno为SC表的外键,其取值分别参照引用Student表的主码和Course表的主码,同时要求:
(1)当删除Student表中元组时,级联删除SC表中相应的元组;
(2)当更新Student表中的Sno时,级联更新SC表相应的元组;
(3)当删除Course表中的元组造成与SC表不一致时,拒绝删除;
(4)当更新Course表中Cno时,级联更新SC表中相应的元组。
原来的定义:
CREATE TABLE SC
(Sno CHAR(8) ,
Cno CHAR(4),
Grade SMALLINT,
PRIMARY KEY(Sno,Cno), /*主码只能定义在表级*/
FOREIGN KEY (Sno) REFERENCES Student(Sno) /*外码定义在表级*/
FOREIGN KEY (Cno) REFERENCES Course(Cno) /*外码定义在表级*/
);
补充:
CREATE TABLE SC
(Sno CHAR(8) ,
Cno CHAR(4),
Grade SMALLINT,
PRIMARY KEY(Sno,Cno), /*主码只能定义在表级*/
FOREIGN KEY (Sno) REFERENCES Student(Sno) /*外码定义在表级*/
ON DELETE CASCADE /*级联删除SC表中相应的元组*/
ON UPDATE CASCADE, /*级联更新SC表中相应的元组*/
FOREIGN KEY (Cno) REFERENCES Course(Cno) /*外码定义在表级*/
ON DELETE NO ACTION /*当删除Course 表中的元组造成了与SC表不一致时拒绝删除*/
ON UPDATE CASCADE /*当更新Course表中的Cno时,级联更新SC表中相应的元组*/
);
🕘 6.4 用户自定义的完整性
- 用户定义的完整性就是针对某一具体应用的数据必须满足的语义要求
- RDBMS提供,而不必由应用程序承担
- 分为属性上的约束和元组上的约束,属性上的约束主要包括
NOT NULL
约束、UNIQUE
约束以及CHECK
约束,元组上的约束可以通过CHECK
约束实现。除此之外,还有关系与关系之间的约束可以通过触发器实现,SQL Server 2014中还存在跟CHECK约束功能相似的规则。
🕤 6.4.1 属性上的约束
可在CREATE TABLE
时定义
- 列值非空(
NOT NULL
) - 列值唯一(
UNIQUE
) - 检查列值是否满足一个布尔表达式(
CHECK
)
例16:定义表Student的同时,定义Sname字段的非空性和性别字段的约束条件。
CREATE TABLE Student
(Sno CHAR(8) PRIMARY KEY,
Sname CHAR(8) NOT NULL,
Ssex CHAR(2) CHECK(Ssex IN('男', '女')) default ‘男’, /*默认为男*/
Sage SMALLINT,
Sdeptno CHAR(4) REFERNCES DEPT(Deptno)
)
🕤 6.4.2 元组上的约束
- 在
CREATE TABLE
时可以用CHECK
短语定义元组上的约束条件,即元组级的限制 - 同属性值限制相比,元组级的限制可以设置不同属性之间的取值的相互约束条件
例17:创建Student表时,添加约束:当学生的性别是男时,其名字不能以Ms.打头。
CREATE TABLE Student
(Sno CHAR(8) PRIMARY KEY,
Sname CHAR(8) NOT NULL,
Ssex CHAR(2) CHECK(Ssex IN(‘男’, ‘女’)) ,
Sage SMALLINT,
Sdeptno CHAR(4) REFERNCES DEPT(Deptno),
CHECK (Ssex='女' OR Sname NOT LIKE 'Ms.%'))
);
- 性别是女性的元组都能通过该项检查,因为Ssex=‘女’成立;
- 当性别是男性时,要通过检查则名字一定不能以Ms.打头
🕤 6.4.3 完整性约束命名子句
- 在定义完整性约束时,可以在约束的前面加上
CONSTRAINT
子句,为约束条件命名,从而更加灵活地增加或删除一个完整性约束。 - 完整性约束命名子句的基本格式为:
CONSTRAINT <完整性约束条件名称> <完整性约束条件>
其中,完整性约束条件可以为NOT NULL
、UNIQUE
、CHECK
短语、PRIMARY KEY
、FOREIGN KEY
等。事实上,这里仅仅是通过CONSTRAINT
子句为所定义的约束取一个名字。
CREATE TABLE Student
(Sno CHAR(8) CONSTRAINT StudentC1 PRIMARY KEY,
Sname CHAR(8) CONSTRAINT StudentC2 NOT NULL,
Ssex CHAR(2) CONSTRAINT StudentC3 CHECK(Ssex IN(‘男’,’女’)),
Sage SMALLINT,
Sdeptno CHAR(4) CONSTRAINT StudentC4 REFERNCES DEPT(Deptno)
);
ALTER TABLE
语句的基本格式分别为:
ALTER TABLE table-name DROP CONSTRAINT <完整性约束条件名称>
ALTER TABLE table-name ADD CONSTRAINT <完整性约束条件名称> <完整性约束条件>
例18:在表Student中,删除外键约束。
ALTER TABLE Student DROP CONSTRAINT StudentC4;
例19:为Student表添加约束,年龄必须在14至45之间。
ALTER TABLE Student ADD CONSTRAINT StudentC5 CHECK(Sage between 14 and 45);
🕘 6.5 规则(了解)
🕤 6.5.1 规则的定义
CREATE RULE rule-name
AS condition_expression
说明:
- 创建的规则对已经存放在数据库中的数据无效。
- 规则表达式的类型必须与列的数据类型兼容,且不能将规则绑定到text、image或timestamp列。
- 如果某列同时有默认值和规则两个约束与之关联,则默认值必须满足规则的定义,与规则冲突的默认值不能关联到列。
例20:创建一个规则,用以限制插入该规则被绑定到的列中的整数的范围在1000到20000之间。
CREATE RULE range_rule
AS @range>= $1000 AND @range <$20000;
例21:创建一个规则,用于将输入到该规则被绑定到的列中的实际值限制为只能是该规则中列出的值。
CREATE RULE list_rule
AS @list IN (‘1389’, ‘0736’, ‘0877’);
例22:创建一个遵循这种模式的规则:任意两个字符的后面跟一个连字符 (-) 和任意多个字符(或没有字符),并以 0 到 9 之间的整数结尾。
CREATE RULE pattern_rule
AS @value LIKE '__-%[0-9]'
🕤 6.5.2 规则对象的绑定
语法格式:
sp_bindrule [ @rulename = ] 'rule-name' ,[ @objname = ] 'object_name’
[ , [ @futureonly = ] 'futureonly_flag' ]
例23:创建一个规则,并绑定到DEPT表的Telephone字段。
CREATE RULE num_rule
AS @num like '[1-3][1-3][1-9] [1-9] [1-9] [1-9] [0-9] [0-9] [0-9] [0-9] [0-9]'
GO
EXEC sp_bindrule 'num_rule', 'DEPT.Telephone'
🕤 6.5.3 规则对象的解绑
语法格式为:
sp_unbindrule [ @object_name = ] ' object_name ‘[ , [ @futureonly = ] 'futureonly_flag' ]
例24:取消别名数据类型ssn的规则绑定。
EXEC sp_unbindrule ssn
EXEC sp_unbindrule 'ssn', 'futureonly' /*现有的无影响,只对将来的有效*/
🕤 6.5.4 规则对象的删除
语法格式为:
DROP RULE {rule}[,…n]
例25:解除num_rule规则对象与DEPT表的Telephone的绑定关系,然后删除规则对象num_rule。
EXEC sp_unbindrule DEPT. Telephone
GO
DROP RULE num_rule
🕘 6.6 触发器☆☆☆
- 触发器是一个被指定关联到一个表的数据对象
- 触发器就是一类靠事件驱动的特殊过程,一旦由某个用户定义,任何用户对该数据的增、删、改操作均由数据库服务器自动激活相应的触发器,在核心层进行集中的完整性控制。
- 一个触发器应包括下面两个功能:
① 指明什么条件下触发器被执行;
② 指明触发器执行什么动作。
🕤 6.6.1 触发器的类型
- DML是数据操纵语言,包括select、insert、delete、update,后三个动作会改变数据,可以创建触发器来捕获动作。
- DDL是数据定义语言,创建库、表、触发器、存储过程、视图等命令,均属于此范畴。
🕞 6.6.1.1 DML触发器☆
- 当数据库中发生数据操纵语言(DML)事件时将激活DML触发器。
- DML事件是针对表或视图的 INSERT、UPDATE或DELETE语句,因而DML触发器可分为INSERT、UPDATE和DELETE 3种类型。
- 根据触发器代码执行的时机,DML触发器可以分为两种:AFTER触发器和INSTEAD OF触发器。
AFTER
触发器是在执行了INSERT、UPDATE和DELETE语句操作之后执行,只能在表上定义,不能在视图上定义。- 而
INSTEAD OF
触发器则代替激活触发器的DML操作执行,即原INSERT、UPDATE和DELETE操作不再执行,由触发器中代码代替其执行。INSTEAD OF 触发器可以定义在表或视图上。
注:在Oracle环境下有before
触发器
🕞 6.6.1.2 DDL触发器
- DDL触发器用于响应各种数据定义语言 (DDL) 事件。这些事件主要对应于SQL中的 CREATE、ALTER 和 DROP 语句,以及执行类似 DDL 操作的某些系统存储过程。
- DDL触发器的主要作用是执行管理操作,如审核系统、控制数据库操作等。通常情况下,DDL触发器主要用于以下一些操作需求:防止对数据库架构进行某些修改,希望数据库中发生某些变化以利于相应数据库架构中的更改等。
- DDL触发器只在响应由T-SQL语言所指定DDL事件时才会触发。
🕞 6.6.1.3 登录触发器
- 登录触发器是由登录(LOGON)事件而激活的触发器,与SQL Server实例建立用户会话时将引发此事件。
- 登录触发器将在登录的身份验证阶段完成之后且用户会话实际建立之前激发。
🕤 6.6.2 创建和修改触发器
不管是DML触发器还是DDL触发器,创建的语句都是CRAETE TRIGGER语句,两者语法格式略有不同:
🕞 6.6.2.1 创建DML触发器
CREATE TRIGGER [架构名.]<触发器名> ON <表名|视图名>
[WITH ENCRYPTION] /*说明是否采用加密方式*/
{FOR| AFTER|INSTEAD OF} /*定义触发器的类型*/
{ [ INSERT ] [ , ] [ UPDATE ] [ , ] [ DELETE ] }
[ WITH APPEND ]
[ NOT FOR REPLICATION ]
AS
{
sql_statement /*T-SQL语句序列*/
}
- 在SQL Server 2014中使用触发器,有两个比较特殊的表用于存放临时数据,分别是
inserted
表(后映象)和deleted
表(前映象)。 - ① inserted表:当向表中插入数据时,INSERT触发器触发执行,新的记录插入到触发器表和inserted表中;
- ② deleted表:用于保存已从表中删除的记录,当触发一个DELETE触发器时,被删除的记录存放到deleted逻辑表中。
例26:定义一个触发器,当删除课程表COURSE中某一门课程时,在学生选课记录表SC中的相应选课记录也全部被删除。
CREATE TRIGGER Delete_Course ON COURSE
For DELETE /*触发事件是DELETE */
AS
BEGIN
Delete from SC
where Cno in
(select Cno from deleted );
END;
🔎 UPDATE/DELETE 语句与 REFERENCE 约束““冲突解决方案。
例27:定义一个触发器,为教师表TEACHER定义完整性规则“教授的工资不得低于4000元,如果低于4000元,自动改为4000元”。
分析:本题的含义是在TEACHER表上建立触发器,当对该表执行UPDATE或INSERT操作时自动触发该触发器,保证教授的工资大于等于4000。
CREATE TRIGGER Insert_Or_Update_Sal ON TEACHER
For INSERT, UPDATE/*触发事件是插入或更新操作*/AS /*定义触发动作体,是T-SQL过程块*/
begin
update TEACHER
set Sal=4000
where Eno in
(Select Eno from inserted where Job='教授' AND Sal < 4000) ;
End
扩展知识:
语句级触发器,那么执行完该语句后,触发动作只发生一次(SSMS默认)
行级触发器,触发动作将执行N(指定行数)次,SSMS实现需要借助游标(因为默认不支持)。
例28:定义触发器,当教师表TEACHER的工资发生变化后就自动在工资变化表Sal_log中增加一条相应记录,包括被修改记录的用户工号、新工资以及修改人和修改时间。
分析:TEACHER表的工资发生变化,包括向表中插入记录及修改工资列的值。
首先建立工资变化表Sal_log。
CREATE TABLE Sal_log
(Eno VARCHAR(6) REFERENCES TEACHER(Eno),
Sal NUMERIC(7,2),
Username VARCHAR(12),
Date Datetime
);
然后在TEACHER表上建立INSERT和UPDATE触发器,可以分开两个创建,也可以创建一个,这里选择创建两个触发器。
CREATE TRIGGER Insert_Sal ON TEACHER
For INSERT /*触发事件是INSERT*/
AS
DECLARE
@neweno varchar(6),
@newsal numeric(7,2) /*声明局部变量*/
BEGIN
select @neweno=eno,@newsal=sal from inserted;/*给局部变量赋值*/
INSERT INTO Sal_log VALUES(
@neweno,@newsal,CURRENT_USER,CURRENT_TIMESTAMP);
END;
CREATE TRIGGER Update_Sal ON TEACHER
For UPDATE /*触发事件是UPDATE */
AS
DECLARE
@neweno Varchar(6),
@newsal numeric(7,2),
@oldsal numeric(7,2)
BEGIN
select @oldsal=sal from deleted;
select @neweno=eno,@newsal=sal from inserted ;
IF (@newsal <> @oldsal)
BEGIN
INSERT INTO Sal_log VALUES(
@neweno,@newsal,CURRENT_USER,CURRENT_TIMESTAMP);
END;
END;
for,instead of,after 3种触发器的区别
FOR | AFTER
AFTER 指定触发器仅在触发 SQL 语句中指定的所有操作都已成功执行后才被触发。所有的引用级联操作和约束检查也必须在激发此触发器之前成功完成。
如果仅指定 FOR 关键字,则 AFTER 为默认值。
不能对视图定义 AFTER 触发器。INSTEAD OF
指定执行 DML 触发器替代原本要执行的SQL 语句,因此,其优先级高于触发语句的操作。
🕞 6.6.2.2 创建DDL触发器
语法格式:
CREATE TRIGGER trigger_name
ON { ALL SERVER | DATABASE }
[ WITH ENCRYPTION ]
{ FOR | AFTER } { event_type | event_group } [ ,...n ]
AS
{
sql_statement /*T-SQL语句序列*/
}
例29:创建一个DDL触发器,禁止删除当前数据库中的任何表。
CREATE TRIGGER safety
ON DATABASE
AFTER DROP_TABLE
AS
BEGIN
PRINT '不能删除数据库表!'
ROLLBACK TRANSACTION
END
🕤 6.6.3 删除触发器
语法如下:
DROP TRIGGER <触发器名>
- 只有该触发器拥有者或被授权者才能撤消。
- 对于触发器的使用,除了创建、修改和删除之外,还可以使用
DISABLE
和ENABLE
语句使触发器无效或激活触发器,
🕒 7. 课后习题
-
【单选题】 关于约束叙述正确的是( )。
A、每个约束只能作用于一个列上
B、每个约束可以作用多个列,但是必须在一个表里
C、每个约束可以作用到多个表的多个列
D、以上都不对 -
【单选题】下列( )是对触发器的描述。
A、定义了一个有相关列和行的集合
B、当用户修改数据时,一种特殊形式的存储过程被自动执行
C、SQL语句的预编译集合
D、它根据一或多列的值,提供对数据库表的行的快速访问 -
【单选题】数据完整性保护中的约束条件主要是指( )。
A、用户操作权限的约束
B、用户口令校对
C、值的约束和结构的约束
D、并发控制的约束 -
【填空题】数据库完整性的定义一般由SQL语句中的________来实现。它们作为数据库模式的一部分存入________中。
-
【填空题】关系模型的元组上的约束条件的定义,在___________中用______关键字来实现。
-
【填空题】在Sno(学号)列上创建约束,要求Sno的值在18至22岁之间,约束名Sno_CK。请写出对应的完整性命名子句_______________。
-
【填空题】在SQL Server中使用触发器时,有两个比较重要的逻辑表可以存放更新前和更新后的数据,分别是( )表和( )表。
-
【判断题】SQL Server中的规则在使用时,若已经绑定了相关的数据库对象,则删除该规则时,会自动解绑然后删除。
-
【简答题】请用SQL语句创建Emp和Dept表,
Emp(Eno, Ename, Eage, Salary, Deptno)
Dept(Deptno, Dname, Phone, Loc)
并存在以下约束。
(1) Dept的主键是Deptno,Emp的主键是Eno。
(2) Emp的外键是Deptno,被参考的关系是Dept。
(3) Emp的 Eage取值在20~60之间,默认值为30。
(4) Dept的Dname值唯一且非空。
(5) Emp的Salary要求必须大于1000。 -
给定employee,创建该表的语句如下:
CREATE TABLE EMPLOYEE
( Eno Char(8) Primary Key,
Ename Varchar(10),
Eage Smallint
Salary Numeric(7,2),
Deptno Char(4)
);
试用触发器表示下列完整性约束:
(1) 20≤Eage≤60;
(2) Salary≤10000;
(3) 当插入或者修改 一个职工记录的时候,如果工资低于1000元则自动改为1000元。
PS:本题可以创建三个触发器也可以创建一个触发器,建议创建三个触发器完成该题。
答案:1.C 2.B 3.C 4.DDL语句、数据字典 5.CREATE TABLE、CHECK 6.
CONSTRAINT Sno_CK PRIMARY KEY CHECK (Sno between 18 and 22) 7.DELETED、INSERTED 8.×
9.
CREATE TABLE DEPT
( Deptno Char(4) Primary Key,
Dname Varchar(10) unique not null,
Phone Varchar(12),
Loc Varchar(50)
);
CREATE TABLE EMP
( Eno Char(8) Primary Key,
Ename Varchar(10),
Eage Smallint Check(Eage >=20 and Eage<=60) default 30,
Salary Numeric(7,2) check (Salary >1000),
Deptno Char(4) References Dept(Deptno)
);
/*(1)*/
create trigger tri_update_eage_emp on employee
for insert,update
as
declare
@Eage smallint /*声明局部变量*/
begin
select @eage=eage from inserted;
if (@eage<20 or @eage>60)
begin
print('年龄不在合法范围内!')
rollback transaction
end
end
/*(2)*/
create trigger tri_update_salary_emp on employee
for insert,update
as
declare
@salary Numeric(7,2)
begin
select @salary = salary from inserted;
if (@salary >10000)
begin
print('工资取值不在有效范围内!')
rollback transaction
end
end
/*(3)*/
create trigger insert_or_update_emp on employee
for insert,update
as
begin
update emp set salary=1000 where eno in
(Select eno from inserted where salary<1000)
end
OK,以上就是本期知识点“安全性与完整性”的知识啦~~ ,感谢友友们的阅读。后续还会继续更新,欢迎持续关注哟📌~
💫如果有错误❌,欢迎批评指正呀👀~让我们一起相互进步🚀
🎉如果觉得收获满满,可以点点赞👍支持一下哟~
❗ 转载请注明出处
作者:HinsCoder
博客链接:🔎 作者博客主页