数据库系统原理 (三): 关系数据库标准语言 SQL

参考《数据库系统概论》

SQL 概述

Structured Query Language

  • SQL 结构化查询语言,是关系数据库的标准语言. SQL 是一个通用的、功能极强的关系数据库语言。其功能并不仅仅是查询

各个 RDBMS 产品在实现标准 SQL 时各有差别,与 SQL 标准的符合程度也不相同, 一般在85%以上。因此,具体使用某个 RDBMS 产品时,还应参阅系统提供的有关手册

SQL 的特点

综合统一

  • SQL 集数据查询(Data Query), 数据操纵 (Data Manipulation), 数据定义 (Data Definition) 和数据控制 (Data Control) 功能于一体
    • SQL 集数据定义语言(DDL),数据操纵语言(DML),数据控制语言(DCL)功能于一体, 可以独立完成数据库生命周期中的全部活动
      • 定义关系模式,插入数据,建立数据库
      • 对数据库中的数据进行查询和更新
      • 数据库重构和维护
      • 数据库安全性、完整性控制等
    • 用户数据库投入运行后,可根据需要随时逐步修改模式,不影响数据的运行
    • 在关系模型中实体和实体间的联系均用关系表示,这种数据结构的单一性带来了数据操作符的统一性,查找、插入、删除、更新等每一种操作都只需一种操作符

高度非过程化

  • 非关系数据模型的数据操纵语言“面向过程”,必须制定存取路径
  • SQL 只要提出“做什么”,无须了解存取路径。存取路径的选择以及 SQL 的操作过程由系统自动完成;不但大大减轻了用户负担,而且有利于提高数据独立性

面向集合的操作方式

  • 非关系数据模型采用面向记录的操作方式,操作对象是一条记录
    • 例如查询所有平均成绩在80分以上的学生姓名,用户必须一条一条地把满足条件的学生记录找出来 (通常要说明具体处理过程,即按照哪条路径,如何循环等)
  • SQL 采用集合操作方式。操作对象、查找结果可以是元组的集合, 一次插入、删除、更新操作的对象可以是元组的集合

以同一种语法结构提供两种使用方法

  • SQL 是独立的语言能够独立地用于联机交互的使用方式, 用户可以在终端键盘上自接键入 SQL 命令对数据库进行操作
  • SQL 又是嵌入式语言,SQL 能够嵌入到高级语言(例如 C,C++,Java)程序中,供程序员设计程序时使用

语言简洁,易学易用

  • SQL 完成核心功能只用了 9 个动词
SQL 功能 动词
数据查询 SELECT
数据定义 CREATE, DROP, ALTER
数据操纵 INSERT, UPDATE, DELETE
数据控制 GRANT, REVOKE

SQL 的基本概念

  • SQL 支持关系数据库三级模式结构; 其中外模式对应于 视图(View) 和部分 基本表(Base Table), 模式对应于基本表,内模式对应于存储文件 (Stored File); 用户可以用 SQL 对基本表和视图进行查询或其他操作,基本表和视图一样,都是关系
    在这里插入图片描述
    • 基本表: 本身独立存在的表; SQL 中一个关系就对应一个基本表. 一个(或多个)基本表对应一个存储文件; 一个表可以带若干索引, 索引也放在存储文件中
    • 存储文件: 逻辑结构组成了关系数据库的内模式; 物理结构是任意的,对用户透明
    • 视图: 从一个或几个基本表导出的表; 数据库中只存放视图的定义而不存放视图对应的数据, 这些数据仍存放在导出视图的基本表中,因此视图是一个虚表. 视图在概念上与基本表等同,用户可以在视图上再定义视图

学生-课程数据库

  • 下面的说明均以 学生-课程数据库 为例

  • 首先要定义一个 学生-课程模式 S-T
    学 生 表 : S t u d e n t ( S n o , S n a m e , S s e x , S a g e , S d e p t ) 课 程 表 : C o u r s e ( C n o , C n a m e , C p n o , C c r e d i t ) 学 生 选 课 表 : S C ( S n o , C n o , G r a d e ) 学生表:Student(Sno,Sname,Ssex,Sage,Sdept)\\ 课程表:Course(Cno,Cname,Cpno,Ccredit)\\ 学生选课表:SC(Sno,Cno,Grade) Student(Sno,Sname,Ssex,Sage,Sdept)Course(Cno,Cname,Cpno,Ccredit)SC(Sno,Cno,Grade)
    • 数据示例:
      在这里插入图片描述

数据定义

  • 关系数据库系统支持三级模式结构,其模式、外模式和内模式中的基本对象有表、视图和索引。因此SQL的数据定义功能: 模式定义表定义视图索引的定义
    • SQL 通常不提供修改模式定义、修改视图定义和修改索引定义的操作。用户如果想修改这些对象,只能先将它们删除掉,然后再重建

在这里插入图片描述

模式的定义与删除

定义模式

CREATE SCHEMA <模式名> AUTHORIZATION <用户名>
  • 如果没有指定 <模式名>,那么 <模式名> 隐含为 <用户名>
  • 要创建模式,调用该命令的用户必须拥有 DBA 权限或者获得了 DBA 授予的 CREATE SCHEMA 的权限

  • 定义模式实际上定义了一个命名空间,在这个空间中可以进一步定义该模式包含的数据库对象,例如基本表、视图、索引等
    • CREATE SCHEMA 中可以接受 CREATE TABLECREATE VIEWGRANT 子句. 也就是说用户可以在创建模式的同时在这个模式定义中进一步创建基本表、视图,定义授权
CREATE SCHEMA <模式名> AUTHORIZATION <用户名> [<表定义子句>|<视图定义子句>|<授权定义子句>]

删除模式

DROP SCHEMA <模式名> <CASCADE|RESTRICT>
  • 其中 CASCADE (级联) 和 RESTRICT (限制) 两者必选其一
    • CASCADE: 删除模式的同时把该模式中所有的数据库对象全部删除
    • RESTRICT: 如果该模式中定义了下属的数据库对象(如表、视图等),则拒绝该删除语句的执行。因此只有当该模式中没有任何下属的对象时才能执行

  • 为用户 WANG 定义一个学生-课程模式 S-T
CREATE SCHEMA "S-T" AUTHORIZATION WANG;

CREATE SCHEMA TEST AUTHORIZATION ZHANG
	CREATE TABLE TAB1(COL1 SMALLINT,
					  COL2 INT,
					  COL3 CHAR(20),
					  COL4 NUMERIC(103), 
					  COL5 DECIMAL(52)
					  );

  • 删除模式 ZHANG, 同时该模式中定义的表 TAB1 也被删除
DROP SCHEMA ZHANG CASCADE;

基本表的定义、删除与修改

数据类型

  • SQL 中的概念用数据类型来实现;定义表的属性时需要指明其数据类型及长度;选用哪种数据类型一般从两方面考虑:
    • 取值范围、要做哪些运算
    • 例如,对于年龄 (Sage) 属性,可以采用 CHAR(3) 作为数据类型,但考虑到要在年龄上做算术运算(如求平均年龄),所以要采用整数作为数据类型,因为 CHAR(n) 数据类型不能进行算术运算。整数又有长整数和短整数两种,因为一个人的年龄在百岁左右,所以选用短整数 SMALLINT 作为年龄的数据类型
      在这里插入图片描述

不同的 RDBMS 中支持的数据类剧不完全相同

定义基本表

  • 创建了一个模式,就建立了—个数据库的命名空间。在这个空间中首先要定义的是该模式包含的数据库基本表

CREATE TABLE <表名>
	( <列名> <数据类型> [ <列级完整性约束条件> ]
	[, <列名> <数据类型>[ <列级完整性约束条件>] ] 
	...
	[, <表级完整性约束条件> ] );
  • <列名>:组成该表的各个属性(列)
  • <列级完整性约束条件>:涉及相应属性列的完整性约束条件
  • <表级完整性约束条件>:涉及一个或多个属性列的完整性约束条件
    • 这些完整性约束条件被存入系统的数据字典中,当用户操作表中数据时由 RDBMS 自动检查该操作是否违背这些完整性约束条件
    • 如果完整性约束条件涉及到该表的多个属性列,则必须定义在表级上,否则既可以定义在列级也可以定义在表级

  • 建立“学生”表 Student,它由学号 Sno、姓名 Sname、性别 Ssex、年龄 Sage、所在系 Sdept 五个属性组成。学号是主码,姓名取值唯一
CREATE TABLE Student
	(Sno CHAR(9) PRIMARY KEY, 	// 列级完整性约束条件
	Sname CHAR(20) UNIQUE, 		// Sname 取唯一值
	Ssex CHAR(2),
	Sage SMALLINT,
	Sdept CHAR(20)
	);

  • 建立一个 “课程” 表 Course
CREATE TABLE Course
	(Cno CHAR(4) PRIMARY KEY,
	Cname CHAR(40),
	Cpno CHAR(4),
	Ccredit SMALLINT,
	FOREIGN KEY (Cpno) REFERENCES Course(Cno) // Cpno 是外码,被参照表是 Course,被参照列是 Cno
	);

  • 建立一个“学生选课”表 SC
CREATE TABLE SC
	(Sno CHAR(9),
	Cno CHAR(4),
	Grade SMALLINT,
	PRIMARY KEY (Sno,Cno),	// 主码由两个属性构成,必须作为表级完整性进行定义
	FOREIGN KEY (Sno) REFERENCES Student(Sno)FOREIGN KEY (Cno) REFERENCES Course(Cno)
	);

模式与表

  • 每一个基本表都属于某一个模式, 一个模式包含多个基本表

定义基本表所属模式

  • (1) 在表名中明显地给出模式名
    • Create table "S-T".Student(......); /*模式名为S-T*/
  • (2) 在创建模式语句中同时创建表
  • (3) 设置所属的模式
    • 当用户创建基本表(其他数据库对象也一样)时,若没有指定模式,系统根据搜索路径来确定该对象所属的模式; 搜索路径包含一组模式列表, RDBMS 会使用模式列表中第一个存在的模式作为数据库对象的模式名; 若搜索路径中的模式名都不存在,系统将给出错误
      • 显示当前的搜索路径: SHOW search_path;
      • 搜索路径的当前默认值是:$userPUBLIC. 其含义是首先搜索与用户名相同的模式名,如果该模式名不存在,则使用 PUBLIC 模式
      • DBA 用户可以设置搜索路径,然后定义基本表: SET search_path TO "S-T", PUBLIC; Create table Student(......); (RDBMS 发现搜索路径中第一个模式名 S-T 存在,就把该模式作为基本表 Student 所属的模式, 最终建立了 S-T.Student 基本表)

修改基本表

ALTER TABLE <表名>
	[ADD <新列名> <数据类型> [完整性约束] ]
	[DROP <完整性约束名> ]
	[ALTER COLUMN <列名> <数据类型> ];
  • 不论基本表中原来是否已有数据,新增加的列一律为空值

  • 向 Student 表增加“入学时间”列,其数据类型为日期型
ALTER TABLE Student ADD S_entrance DATE;

  • 将年龄的数据类型由字符型改为整数
ALTER TABLE Student ALTER COLUMN Sage INT;

  • 增加课程名称必须取唯一值的约束条件
ALTER TABLE Course ADD UNIQUE(Cname);

删除基本表

DROP TABLE <表名> [RESTRICT|CASCADE];
  • RESTRICT (默认):欲删除的基本表不能被其他表的约束所引用 (如 CHECK, FOREIGN KEY 等约束), 不能有视图,不能有触发器,不能有存储过程或函数等。如果存在依赖该表的对象,则此表不能被删除
  • CASCADE:删除该表没有限制; 在删除基本表的同时,相关的依赖对象一起删除 (表上建立的索引、视图、触发器等一般也将被删除)

不同的数据库产品在遵循 SQL 标准的基础上具体实现细节和处理策略上会与标准有差别。因此,如果发现本书中个别例子在某个数据库产品上不能通过时,请读者参见有关产品的用户手册适当修改即可


  • 删除 Student 表
DROP TABLE Student CASCADE;

  • 若表上建有视图,选择 RESTRICT 时表不能删除
CREATE VIEW IS_Student 		// Student 表上建立视图
AS
	SELECT Sno, Sname, Sage FROM Student
	WHERE Sdept='IS';
> DROP TABLE Student RESTRICT;
--ERROR: cannot drop table Student because other objects depend on it
	
> DROP TABLE Student CASCADE;
--NOTICE: drop cascades to view IS_Student		// 选择 CASCADE 时可以删除表,视图也自动被删除

> SELECT * FROM IS_Student;
--ERROR: relation " IS_Student " does not exist

索引的建立与删除

参考: 【数据库索引Index系列】数据库索引,这一篇就够了

  • 数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询,更新数据库中表的数据, 这些数据结构以某种方式引用数据. 在基本表上建立一个或多个索引,可以提供多种存取路径,加快查询速度. 系统在存取数据时会自动选择合适的索引作为存取路径,用户不必也不能显式地选择索引
    • 一般说来,建立与删除索引由 数据库管理员DBA表的属主(owner, 即建立表的人) 负责完成
    • DBMS 一般会自动建立以下列上的索引: PRIMARY KEY, UNIQUE
  • 索引是关系数据库的内部实现技术,属于内模式的范畴
    • RDBMS 中索引一般采用 B+树、HASH 索引来实现; B+ 树索引具有动态平衡的优点; HASH 索引具有查找速度快的特点; 采用 B+ 树,还是 HASH 索引则由具体的 RDBMS 来决定

建立索引

CREATE [UNIQUE] [CLUSTER] INDEX <索引名>
	ON <表名>(<列名>[<次序>][,<列名>[<次序>] ]...);
  • 定义索引时,可以定义索引是唯一索引非唯一索引聚簇索引
    • UNIQUE 表明此索引的每一个索引值只对应唯一的数据记录, 可以保证数据库表中每一行数据的唯一性
    • CLUSTER 表示要建立的索引是聚簇索引。所谓聚簇索引是指索引项的顺序与表中记录的物理顺序一致的索引组织;它会根据聚簇索引键的顺序对表的数据进行排序,然后重新存储到磁盘上
      • 比如字典中,用‘拼音’查汉字,就是聚簇索引。因为正文中字都是按照拼音排序的。而用‘偏旁部首’查汉字,就是非聚簇索引,因为正文中的字并不是按照偏旁部首排序的,我们通过检字表得到正文中的字在索引中的映射,然后通过映射找到所需要的字
      • 显然在一个基本表上最多只能建立一个聚簇索引;用户可以在最经常查询的列上建立聚簇索引以提高查询效率
      • 建立聚簇索引后,更新该索引列上的数据时,往往导致表中记录的物理顺序的变更,代价较大,因此对于经常更新的列不宜建立聚簇索引
  • <表名> 是要建索引的基本表的名字。索引可以建立在该表的一列或多列上,各列名之间用逗号分隔。各个 <列名> 后还可以用 <次序> 指定索引值的排列次序,可选 ASC (升序) 或 DESC (降序),缺省值为 ASC

  • 在 Student 表的 Sname(姓名)列上建立一个聚簇索引, 而且 Student 表中的记录将按照 Sname 值的升序存放
CREATE CLUSTER INDEX Stusname ON Student(Sname);

  • 为学生-课程数据库中的 Student,Course,SC 三个表建立索引
    • Student 表按学号升序建唯一索引
    • Course 表按课程号升序建唯一索引
    • SC 表按学号升序和课程号降序建唯一索引
CREATE UNIQUE INDEX Stusno ON Student(Sno);
CREATE UNIQUE INDEX Coucno ON Course(Cno);
CREATE UNIQUE INDEX SCno ON SC(Sno ASC,Cno DESC);

删除索引

  • 索引一经建立,就由系统使用和维护它,不需用户干预
  • 建立索引是为了减少查询操作的时间,但如果数据增删改频繁,系统会花费许多时间来维护索引, 而且时间随着数据量的增加而增大,从而降低了查询效率;同时,索引需要占用物理空间,如果要建立聚簇索引,所需要的空间会更大;这时可以删除一些不必要的索引
DROP INDEX <索引名>;
  • 删除索引时,系统会从数据字典中删去有关该索引的描述

  • 删除 Student 表的 Stusname 索引
DROP INDEX Stusname;

数据查询

SELECT [ALL|DISTINCT] <目标列表达式> [, <目标列表达式>] ...
	FROM <表名或视图名>[, <表名或视图名>] ...
	[WHERE <条件表达式>]
	[GROUP BY <列名1> [HAVING <条件表达式>]]
	[ORDER BY <列名2> [ASC|DESC]];
  • 整个 SELECT 语句的含义是,根据 WHERE 子句的条件表达式,从 FROM 子句指定的基本表或视图中找出满足条件的元组,再按 SELECT 子句中的目标列表达式,选出元组中的属性值形成结果表 (先选择后投影)
  • 如果有 GROUP BY 子句,则将结果按 <列名1> 的值进行分组,该属性列值相等的元组为一个组。通常会在每组中作用聚集函数(aggregate functions) , 如果 GROUP BY 子句带 HAVING 短语,则只有满足指定条件的组才予以输出
  • 如果有 ORDER BY 子句,则结果表还要按 <列名2> 的值的升序或降序排序

单表查询

  • 单表查询: 查询仅涉及一个表

选择表中的若干列

  • 选择表中的全部列或部分列,这就是关系代数的投影运算

查询指定列

  • 查询全体学生的学号与姓名
    • 该语句的执行过程可以是这样的,从 Student 表中取出一个元组,取出该元组在属性 Sno 和 Sname 上的值,形成一个新的元组作为输出。对 Student 表中的所有元组做相同的处理,最后形成一个结果关系作为输出
SELECT Sno, Sname FROM Student;

选出所有属性列

  • SELECT 关键字后面列出所有列名; 或 将 <目标列表达式> 指定为 *

  • 查询全体学生的详细记录
SELECT Sno, Sname, Ssex, Sage, Sdept FROM Student;
SELECT * FROM Student;

查询经过计算的值

  • SELECT 子句的 <目标列表达式> 可以为:
    • 算术表达式, 字符串常量, 函数, 列别名

  • 查全体学生的姓名及其出生年份
SELECT Sname, 2021-Sage /*假定当年的年份为2021年*/ FROM Student;
  • 输出结果:
    在这里插入图片描述

  • 查询全体学生的姓名、出生年份和所有系,要求用小写字母表示所有系名
SELECT Sname, 'Year of Birth:', 2004-Sage, ISLOWER(Sdept) FROM Student;
  • 输出结果:
    在这里插入图片描述
  • 使用列别名改变查询结果的列标题:
SELECT Sname NAME, 'Year of Birth:' BIRTH, 
	2000-Sage BIRTHDAY, ISLOWER(Sdept) DEPARTMENT FROM Student;
  • 输出结果:
    在这里插入图片描述

选择表中的若干元组

消除取值重复的行

  • 如果没有指定 DISTINCT 关键词,则缺省为 ALL

  • 查询选修了课程的学生学号
SELECT Sno FROM SC;
// 等价于
SELECT ALL Sno FROM SC;
  • 结果如下:
    在这里插入图片描述
SELECT DISTINCT Sno FROM SC;
  • 结果如下:
    在这里插入图片描述

查询满足条件的元组

  • 查询满足指定条件的元组可以通过 WHERE 子句实现, WHERE 子句常用的查询条件如下表所示
    在这里插入图片描述
    • !=<> 都表示 “不等于”; !> (不大于)

比较大小

  • 查询计算机科学系全体学生的名单
SELECT Sname FROM Student WHERE Sdept='CS';

  • 查询考试成绩有不及格的学生的学号
SELECT DISTINCT Sno FROM SC WHERE Grade<60;

确定范围

  • 查询年龄在20~23岁(包括20岁和23岁)之间的学生的姓名、系别和年龄
SELECT Sname, Sdept, Sage FROM Student
	WHERE Sage BETWEEN 20 AND 23;

  • 查询年龄不在20~23岁之间的学生姓名、系别和年龄
SELECT Sname, Sdept, Sage FROM Student
	WHERE Sage NOT BETWEEN 20 AND 23;

确定集合

  • 查询信息系(IS)、数学系(MA)和计算机科学系(CS)学生的姓名和性别
// 也可用 OR 实现
SELECT Sname, Ssex FROM Student WHERE Sdept IN ( 'IS', 'MA', 'CS' );

  • 查询既不是信息系、数学系,也不是计算机科学系的学生的姓名和性别
SELECT Sname, Ssex FROM Student WHERE Sdept NOT IN ( 'IS', 'MA', 'CS' );

字符匹配

[NOT] LIKE '<匹配串>' [ESCAPE '<换码字符>']
  • % 用于匹配若干个任意符号;_ 用于匹配单个任意符号

  • 查询学号为 200215121 的学生的详细情况
SELECT * FROM Student WHERE Sno LIKE '200215121';

  • 查询所有姓刘学生的姓名、学号和性别
SELECT Sname, Sno, Ssex FROM Student WHERE Sname LIKE '刘%';

  • 查询姓"欧阳"且全名为三个汉字的学生的姓名
SELECT Sname FROM Student WHERE Sname LIKE '欧阳_';

  • 查询名字中第2个字为"阳"字的学生的姓名和学号
SELECT Sname, Sno FROM Student WHERE Sname LIKE '__阳%';

  • 查询所有不姓刘的学生姓名
SELECT Sname, Sno, Ssex FROM Student WHERE Sname NOT LIKE '刘%';

  • 查询以 DB_ 开头,且倒数第3个字符为 i 的课程的详细情况
SELECT * FROM Course WHERE Cname LIKE 'DB\_%i__' ESCAPE '\';

涉及空值的查询

  • 谓词: IS NULLIS NOT NULL; IS” 不能用 “=” 代替

  • 某些学生选修课程后没有参加考试,所以有选课记录,但没有考试成绩。查询缺少成绩的学生的学号和相应的课程号
SELECT Sno, Cno FROM SC WHERE Grade IS NULL

多重条件查询

  • 逻辑运算符:ANDOR 来联结多个查询条件
    • 可用来实现多种其他谓词: [NOT] IN, [NOT] BETWEEN … AND …

  • 查询计算机系年龄在20岁以下的学生姓名
SELECT Sname FROM Student WHERE Sdept='CS' AND Sage<20;

ORDER BY 子句

  • ORDER BY 子句: 可以按一个或多个属性列排序
    • 升序:ASC;降序:DESC;缺省值为升序
    • 当排序列含空值时
      • ASC:排序列为空值的元组最后显示
      • DESC:排序列为空值的元组最先显示

  • 查询选修了3号课程的学生的学号及其成绩,查询结果按分数降序排列
SELECT Sno, Grade FROM SC WHERE Cno='3'
	ORDER BY Grade DESC;

  • 查询全体学生情况,查询结果按所在系的系号升序排列,同一系中的学生按年龄降序排列
SELECT * FROM Student ORDER BY Sdept, Sage DESC;

聚集函数

计数

COUNT ([DISTINCT|ALL] *) 
COUNT ([DISTINCT|ALL] <列名>)

计算总和

SUM ([DISTINCT|ALL] <列名>)

计算平均值

AVG ([DISTINCT|ALL] <列名>)

最大最小值

MAX ([DISTINCT|ALL] <列名>) 
MIN ([DISTINCT|ALL] <列名>)

  • 查询学生总人数
SELECT COUNT(*) FROM Student;

  • 查询选修了课程的学生人数
SELECT COUNT(DISTINCT Sno) FROM SC;

  • 查询选修1号课程的学生最高分数
SELECT MAX(Grade) FROM SC WHERE Cno='1';

  • 查询学生200215012选修课程的总学分数
SELECT SUM(Ccredit) FROM SC, Course 
	WHERE Sno='200215012' AND SC.Cno=Course.Cno;

GROUP BY 子句

  • GROUP BY 子句分组:按指定的一列或多列值分组,值相等的为一组
    • 未对查询结果分组,聚集函数将作用于整个查询结果
    • 对查询结果分组后,聚集函数将分别作用于每个组
  • HAVING 短语WHERE 子句的区别:
    • WHERE 子句作用于基表或视图,从中选择满足条件的元组
    • HAVING 短语作用于组,从中选择满足条件的组

  • 求各个课程号及相应的选课人数
SELECT Cno, COUNT(Sno) FROM SC GROUP BY Cno;

  • 查询选修了3门以上课程的学生学号
SELECT Sno FROM SC GROUP BY Sno HAVING COUNT(*)>3;

  • 查询不及格课程数超过两门的学生学号
select Sno from SC where grade < 60 group by Sno having count(*) > 2

连接查询

  • 连接查询:同时涉及多个表的查询
    • 连接条件连接谓词:用来连接两个表的条件
    • 连接字段:连接谓词中的列名称; 连接条件中的各连接字段类型必须是可比的,但名字不必是相同的
  • 一般格式:
[<表名1>.]<列名1>  <比较运算符>  [<表名2>.]<列名2>
[<表名1>.]<列名1> BETWEEN [<表名2>.]<列名2> AND [<表名2>.]<列名3>

如果一个列名在多个表中都是唯一的,则 <表名> 可加可不加


连接操作的执行过程

  • 嵌套循环法 (NESTED-LOOP)
    • 首先在表1中找到第一个元组,然后从头开始扫描表2,逐一查找满足连接条件的元组,找到后就将表1中的第一个元组与该元组拼接起来,形成结果表中一个元组
    • 表2全部查找完后,再找表1中第二个元组,然后再从头开始扫描表2,逐一查找满足连接条件的元组,找到后就将表1中的第二个元组与该元组拼接起来,形成结果表中一个元组
    • 重复上述操作,直到表1中的全部元组都处理完毕
  • 排序合并法 (SORT-MERGE) (常用于等值连接)
    • 首先按连接属性对表1和表2排序
    • 对表1的第一个元组,从头开始扫描表2,顺序查找满足连接条件的元组,找到后就将表1中的第一个元组与该元组拼接起来,形成结果表中一个元组。当遇到表2中第一条大于表1连接字段值的元组时,对表2的查询不再继续
    • 找到表1的第二条元组,然后从刚才的中断点处继续顺序扫描表2,查找满足连接条件的元组,找到后就将表1中的第一个元组与该元组拼接起来,形成结果表中一个元组。直接遇到表2中大于表1连接字段值的元组时,对表2的查询不再继续
    • 重复上述操作,直到表1或表2中的全部元组都处理完毕为止
  • 索引连接 (INDEX-JOIN)
    • 对表2按连接字段建立索引
    • 对表1中的每个元组,依次根据其连接字段值查询表2的索引,从中找到满足条件的元组,找到后就将表1中的第一个元组与该元组拼接起来,形成结果表中一个元组

等值与非等值连接查询

  • 查询每个学生及其选修课程的情况
// 等值连接
SELECT Student.*, SC.* FROM Student, SC
	WHERE Student.Sno = SC.Sno;
// 等价于
SELECT * FROM Student, SC
	WHERE Student.Sno = SC.Sno;
  • 查询结果:
    在这里插入图片描述
// 自然连接
SELECT Student.Sno, Sname, Ssex, Sage, Sdept, Cno, Grade 
	FROM   Student, SC
	WHERE  Student.Sno = SC.Sno;

自身连接

  • 自身连接:一个表与其自己进行连接
    • 需要给表起别名以示区别; 由于所有属性名都是同名属性,因此必须使用别名前缀

  • 查询每一门课的间接先修课(即先修课的先修课)
SELECT FIRST.Cno, SECOND.Cpno 
	FROM Course FIRST, Course SECOND 
	WHERE FIRST.Cpno = SECOND.Cno;

外连接

  • 普通连接操作只输出满足连接条件的元组, 外连接操作以指定表为连接主体,将主体表中不满足连接条件的元组一并输出

// 左外连接
SELECT Student.Sno, Sname, Ssex, Sage, Sdept, Cno, Grade
	FROM Student LEFT OUT JOIN SC ON (Student.Sno=SC.Sno);
  • 执行结果 (没有选课的学生信息也被列出来了):
    在这里插入图片描述

复合条件连接

  • 复合条件连接WHERE 子句中含多个连接条件

  • 查询选修2号课程且成绩在90分以上的所有学生
SELECT Student.Sno, Sname
	FROM   Student, SC
	WHERE  Student.Sno = SC.Sno AND SC.Cno='2' AND SC.Grade > 90;

  • 查询每个学生的学号、姓名、选修的课程名及成绩
SELECT Student.Sno, Sname, Cname, Grade
	FROM Student, SC, Course 	/*多表连接*/
	WHERE Student.Sno = SC.Sno and SC.Cno = Course.Cno;

嵌套查询

  • 嵌套查询: 一个 SELECT-FROM-WHERE 语句称为一个查询块. 将一个查询块嵌套在另一个查询块的 WHERE 子句或 HAVING 短语的条件中的查询称为嵌套查询
    • 子查询不能使用 ORDER BY 子句
    • 有些嵌套查询可以用连接运算替代
SELECT Sname /*外层查询/父查询*/
FROM Student
WHERE Sno IN
	(SELECT Sno /*内层查询/子查询*/
	FROM SC
	WHERE Cno= '2');

嵌套查询求解方法

  • 不相关子查询:子查询的查询条件不依赖于父查询
    • 由里向外 逐层处理。即每个子查询在上一级查询处理之前求解,子查询的结果用于建立其父查询的查找条件
  • 相关子查询:子查询的查询条件依赖于父查询
    • 首先取外层查询中表的第一个元组,根据它与内层查询相关的属性值处理内层查询,若 WHERE 子句返回值为真,则取此元组放入结果表, 然后再取外层表的下一个元组
    • 重复这一过程,直至外层表全部检查完为止

带有 IN 谓词的子查询

  • 查询与“刘晨”在同一个系学习的学生。此查询要求可以分步来完成。先确定“刘晨”所在系名 (CS),再查找所有在 CS 系学习的学生; 此查询为不相关子查询
SELECT Sno, Sname, Sdept
FROM Student
WHERE Sdept  IN
	(SELECT Sdept
	FROM Student
	WHERE Sname= '刘晨');

// 等价于以下的自身连接操作
SELECT S1.Sno, S1.Sname, S1.Sdept
FROM Student S1, Student S2
WHERE S1.Sdept = S2.Sdept AND S2.Sname = '刘晨';

  • 查询选修了课程名为“信息系统”的学生学号和姓名
SELECT Sno, Sname 				// 3. 在 Student 关系中取出 Sno 和 Sname
FROM Student 
WHERE Sno IN
	(SELECT Sno 				// 2. 查找选修 3 号课程的学生学号
	FROM SC 
	WHERE Cno IN
		(SELECT Cno 			// 1. 查找 “信息系统” 的课程号 (3 号)
		FROM Course
		WHERE Cname='信息系统'
		)
);

// 等价的连接操作
SELECT Sno,Sname
FROM Student, SC, Course 
WHERE Student.Sno = SC.Sno  AND
	SC.Cno = Course.Cno AND 
	Course.Cname='信息系统';

  • 查询不及格课程数超过两门的学生学号及平均成绩
select sno, avg(grade)
from sc
where sno in(
	select sno 
	from sc
	where grade < 60
	group by sno having count(*) > 2
	)
group by sno;

带有比较运算符的子查询

  • 当能确切知道内层查询返回单值时,可用比较运算符; 同时可以与 ANYALL 谓词配合使用

  • 假设一个学生只可能在一个系学习,并且必须属于一个系,则可以用 = 代替 IN
SELECT Sno,Sname,Sdept
FROM   Student
WHERE  Sdept  =
	(SELECT Sdept
	FROM    Student
	WHERE Sname= '刘晨');
SELECT Sno,Sname,Sdept
FROM   Student
WHERE  (SELECT Sdept
		FROM    Student
		WHERE Sname= '刘晨')
		= Sdept;	// 错误,子查询一定要跟在比较符之后

  • 找出每个学生超过他选修课程平均成绩的课程号
// 相关子查询
SELECT Sno, Cno
FROM  SC  x
WHERE Grade >= (SELECT AVG(Grade) 
				FROM  SC y
				WHERE y.Sno=x.Sno);
  • 可能的执行过程:
    • (1) 从外层查询中取出 SC 的一个元组 x,将元组 x 的 Sno 值(200215121)传送给内层查询
    • (2) 执行内层查询,得到值 88(近似值),用该值代替内层查询,得到外层查询
    • (3) 外层查询取出下一个元组重复做上述1至2步骤,直到外层的 SC 元组全部处理完毕
// (1)
SELECT AVG(Grade) 
FROM SC y 
WHERE y.Sno='200215121';

// (2)
SELECT Sno, Cno 
FROM   SC x
WHERE  Grade >= 88;

带有 ANY (SOME)或 ALL 谓词的子查询

  • ANY:任意一个值
  • ALL:所有值

需要配合使用比较运算符

在这里插入图片描述


ANY(或 SOME),ALL 谓词与聚集函数、IN 谓词的等价转换关系

在这里插入图片描述


  • 查询其他系中比计算机科学某一学生年龄小的学生姓名和年龄
SELECT Sname,Sage
FROM   Student
WHERE  Sage < ANY(SELECT  Sage
					FROM    Student
					WHERE  Sdept= 'CS') 
	   AND Sdept <> 'CS';
  • RDBMS 执行此查询时,首先处理子查询,找出 CS 系中所有学生的年龄,构成一个集合 (20,19). 然后再处理父查询,找所有不是 CS 系且年龄小于 20 或 19 的学生
// 聚集函数实现
SELECT Sname, Sage FROM Student
WHERE  Sage < (SELECT MAX(Sage)
				FROM Student
				WHERE Sdept= 'CS') 
		AND Sdept <> 'CS';

  • 查询所有成绩都不及格的学生姓名
select sname from Student
where 60 > all(select grade 
				from SC
				where SC.sno = Student.sno);

  • 查询 001 号课程成绩最高的所有学生的姓名 (可能并列)
select sname from Student
where cno = '001' and grade >= all(select grade 
									from SC
									where Cno = '001')

  • 查询张三成绩最低的课程号
select cno from SC, Student
where grade <= all(select grade
					from SC SC1
					where SC1.sno = Student.sno)
		and Student.sname = '张三' and Student.sno = sc.sno;

带有 EXISTS 谓词的子查询

  • EXISTS 谓词
    • 存在量词
    • 带有 EXISTS 谓词的子查询不返回任何数据,只产生逻辑值 “true” 或 “false”; 由 EXISTS 引出的子查询,其目标列表达式通常都用 *,因为带 EXISTS 的子查询只返回真值或假值,给出列名无实际意义
      • 若内层查询结果非空,则外层的 WHERE 子句返回真值
      • 若内层查询结果为空,则外层的 WHERE 子句返回假值
  • NOT EXISTS 谓词
    • 若内层查询结果非空,则外层的 WHERE 子句返回假值
    • 若内层查询结果为空,则外层的 WHERE 子句返回真值

不同形式的查询间的替换

  • 一些带 EXISTSNOT EXISTS 谓词的子查询不能被其他形式的子查询等价替换
  • 所有带 IN 谓词、比较运算符、ANYALL 谓词的子查询都能用带 EXISTS 谓词的子查询等价替换

  • 查询所有选修了1号课程的学生姓名
// 嵌套查询
SELECT Sname
FROM   Student
WHERE  EXISTS
			(SELECT * 
			FROM SC
			WHERE Sno=Student.Sno 
				AND Cno='1');
// 连接运算
SELECT Sname
FROM   Student, SC
WHERE  Student.Sno=SC.Sno AND SC.Cno='1';

  • 查询没有选修1号课程的学生姓名
SELECT Sname
FROM Student
WHERE NOT EXISTS
		(SELECT *
		FROM SC
		WHERE Sno=Student.Sno AND Cno='1');

  • 查询与“刘晨”在同一个系学习的学生学号、名字、所在系
SELECT Sno, Sname, Sdept 
FROM Student S1
WHERE EXISTS (SELECT *
				FROM  Student S2
				WHERE S2.Sdept = S1.Sdept AND
					S2.Sname = '刘晨');

  • 查询选修张三老师主讲课程的所有同学的姓名
select sname from Student
where EXISTS (select *
				from SC, Course
				where SC.sno = Student.sno
					and SC.cno = Course.cno
					and Course.Tname = '张三');

EXISTS/NOT EXISTS 实现全称量词

  • SQL 语言中没有全称量词 ; 可以把带有全称量词的谓词转换为等价的带有存在量词的谓词:
    ( ∀ x ) P ≡ ¬ ( ∃ x ( ¬ P ) ) (∀x)P ≡ ¬(∃x(¬P)) (x)P¬(x(¬P))

  • 查询选修了全部课程的学生姓名
SELECT Sname
FROM Student 		// 所要查询的学生,不存在一门课程他没有选修。即该学生没有一门课程是他不选修的
WHERE NOT EXISTS	
	(SELECT *		// 找出学生Student.Sno没有选修的课程情况
	FROM Course 
	WHERE NOT EXISTS
		(SELECT * 	// 查询出学生Student.Sno选修课程Course.Cno的记录
		FROM SC
		WHERE Sno = Student.Sno AND 
			Cno = Course.Cno)
	);

EXISTS/NOT EXISTS 实现逻辑蕴函
p → q = ¬ p ∨ q p → q = ¬p∨q pq=¬pq

  • 查询至少选修了学生200215122选修的全部课程的学生号码
  • 解题思路:用 S C ( s , c ) SC(s,c) SC(s,c) 表示谓词:学生 s s s 选修了课程 c c c; 则上述查询为:
    ( ∀ c ) ( S C ( 200215122 , c ) → S C ( s , c ) )    ⟺    ¬ ( ∃ c ) ( S C ( 200215122 , c ) ∧ ¬ S C ( s , c ) ) (\forall c)(SC(200215122,c)→ SC(s,c)) \\\iff¬(∃c)(SC(200215122,c) ∧¬SC(s,c)) (c)(SC(200215122,c)SC(s,c))¬(c)(SC(200215122,c)¬SC(s,c))
SELECT DISTINCT Sno 
FROM SC SCX
WHERE NOT EXISTS
	(SELECT *
	FROM SC SCY
	WHERE SCY.Sno = '200215122' AND
		NOT EXISTS 
		(SELECT *
		FROM SC SCZ
		WHERE SCZ.Sno=SCX.Sno AND 				
				SCZ.Cno=SCY.Cno));

集合查询

  • 并操作 UNION
    • UNION:将多个查询结果合并起来时,系统自动去掉重复元组
    • UNION ALL:将多个查询结果合并起来时,保留重复元组
  • 交操作 INTERSECT
  • 差操作 EXCEPT
    • 参加集合操作的各查询结果的列数必须相同;对应项的数据类型也必须相同

  • 查询计算机科学系的学生及年龄不大于19岁的学生
// 方法一
SELECT *
FROM Student 
WHERE Sdept= 'CS' 
UNION
SELECT *
FROM Student 
WHERE Sage<=19;
// 方法二
SELECT DISTINCT  *
FROM Student
WHERE Sdept= 'CS'  OR  Sage<=19;

  • 查询选修了课程1或者选修了课程2的学生
SELECT Sno FROM SC
WHERE Cno='1' 
UNION
SELECT Sno FROM SC
WHERE Cno='2'

  • 查询计算机科学系的学生与年龄不大于19岁的学生的交集
SELECT * FROM  Student 
WHERE Sdept='CS' 
INTERSECT 
SELECT * FROM  Student 
WHERE Sage<=19

// 等价于
SELECT *
FROM  Student
WHERE Sdept= 'CS' AND  Sage<=19;

  • 查询计算机科学系的学生与年龄不大于19岁的学生的差集
SELECT * FROM Student 
WHERE Sdept='CS'
EXCEPT
SELECT * FROM Student 
WHERE Sage <=19;

// 等价于
SELECT *
FROM Student
WHERE Sdept='CS' AND  Sage>19;

数据更新

插入数据

插入元组

INSERT
INTO <表名> [(<属性列1>[, <属性列2 >...)] 
VALUES (<常量1> [, <常量2>]...)
  • INTO 子句: 可以不指定属性列 (则 VALUES 子句中常量顺序必须与表中原有属性顺序一致);也可以只指定部分或全部属性列,属性列的顺序可与表定义中的顺序不一致,空缺的属性值将被自动赋空值 NULL
  • VALUES 子句: 提供的值必须与 INTO 子句匹配 (值的个数, 值的类型)

  • RDBMS 在执行插入语句时会检查所插元组是否破坏表上已定义的完整性规则
    • 实体完整性:一定要插入主码
    • 参照完整性
    • 用户定义的完整性: NOT NULL 约束, UNIQUE 约束, 值域约束

  • 将一个新学生元组(学号:200215128;姓名:陈冬;性别:男;所在系:IS;年龄:18岁)插入到 Student 表中
INSERT
INTO  Student (Sno, Sname, Ssex, Sdept, Sage) 
VALUES ('200215128', '陈冬', '男', 'IS', 18);

  • 将学生张成民的信息插入到 Student 表中
INSERT
INTO  Student
VALUES ('200215126', '张成民', '男', 18, 'CS'); 

插入子查询结果

INSERT
INTO <表名>  [(<属性列1> [, <属性列2>...)]
子查询;
  • 将子查询结果插入指定表中 (可以一次插入多个元组)
  • 子查询: SELECT 子句目标列必须与 INTO 子句匹配 (值的个数, 值的类型)

  • 对每一个系,求学生的平均年龄,并把结果存入数据库
// 建表
CREATE  TABLE  Dept_age
(Sdept  CHAR(15) 
Avg_age SMALLINT);

// 插入数据
INSERT
INTO  Dept_age(Sdept,Avg_age)
SELECT  Sdept, AVG(Sage) FROM  Student
GROUP BY Sdept;

修改数据

UPDATE  <表名>
SET  <列名>=<表达式>[, <列名>=<表达式>]...
[WHERE <条件>];
  • WHERE 子句指定要修改的元组; 缺省表示要修改表中的所有元组

  • RDBMS 在执行修改语句时会检查修改操作是否破坏表上已定义的完整性规则
  • 实体完整性: 主码不允许修改
  • 用户定义的完整性: NOT NULL 约束, UNIQUE 约束, 值域约束

  • 将学生200215121的年龄改为22岁
UPDATE Student 
SET Sage=22
WHERE Sno='200215121';

  • 将所有学生的年龄增加1岁
UPDATE Student
SET Sage=Sage+1;

  • 将计算机科学系全体学生的成绩置零
UPDATE SC
SET Grade=0
WHERE 'CS'= (SELECT Sdept
			FROM Student
			WHERE Student.Sno = SC.Sno);

删除数据

DELETE
FROM <表名>
[WHERE <条件>];
  • WHERE 子句指定要删除的元组; 缺省表示要删除表中的全部元组,表的定义仍在字典中

  • 删除学号为 200215128 的学生记录
DELETE
FROM Student
WHERE Sno ='200215128';

  • 删除所有的学生选课记录。
DELETE
FROM SC;

  • 删除计算机科学系所有学生的选课记录
DELETE
FROM SC
WHERE 'CS'= (SELECT Sdept
			FROM Student
			WHERE Student.Sno=SC.Sno);

视图

视图的特点

  • 虚表,是从一个或几个基本表(或视图)导出的表
  • 数据库只存放视图的定义,不存放视图对应的数据,这些数据仍存放在原来的基本表中,基表中的数据发生变化,从视图中查询出的数据也随之改变

基于视图的操作

  • 查询、删除、受限更新 (增删改)、定义基于该视图的新视图

定义视图

建立视图

CREATE VIEW <视图名> [(<列名>  [,<列名>])]
AS <子查询>
[WITH CHECK OPTION];
  • 子查询可以是任意复杂的 SELECT 语句,但通常不允许含有 ORDER BY 子句和 DISTINCT 短语
    • RDBMS 执行 CREATE VIEW 语句时只是把视图定义存入数据字典,并不执行其中的 SELECT 语句; 在对视图查询时,按视图的定义从基本表中将数据查出
  • WITH CHECK OPTION 表示对视图进行 UPDATE, INSERTDELETE 操作时要保证更新、插入或删除的行满足视图定义中的谓词条件(即子查询中的条件表达式)
  • 组成视图的属性列名:全部省略或全部指定,没有第三种选择;如果省略视图的各个属性列名,则隐含该视图由子查询中 SELECT 子句目标列中的诸字段组成;但在下列三种情况下必须明确指定组成视图的所有列名:
    • (1) 某个目标列不是单纯的属性名,而是聚集函数或列表达式
    • (2) 多表连接时选出了几个同名列作为视图的字段
    • (3) 需要在视图中为某个列启用新的更合适的名字

  • 建立信息系学生的视图
CREATE VIEW IS_Student 
AS 
SELECT Sno, Sname, Sage 
FROM Student
WHERE Sdept='IS';

  • 建立信息系学生的视图,并要求进行修改和插入操作时仍需保证该视图只有信息系的学生
CREATE VIEW IS_Student 
AS 
SELECT Sno, Sname, Sage 
FROM Student
WHERE Sdept='IS'
WITH CHECK OPTION;
  • WITH CHECK OPTION 选项时对 IS_Student 视图的更新操作:
    • 修改操作:自动加上 Sdept = 'IS' 的条件
    • 删除操作:自动加上 Sdept = 'IS' 的条件
    • 插入操作:自动检查 Sdept 属性值是否为 ‘IS’; 如果不是,则拒绝该插入操作; 如果没有提供 Sdept 属性值,则自动定义 Sdept 为 ‘IS’

基于多个基表的视图

  • 建立信息系选修了1号课程的学生视图
// 由于视图 IS_S1 的属性列中包含了 Student 表与 SC 表的同名列 Sno, 所以必须在视图名后面明确说明视图的各个属性列名
CREATE VIEW IS_S1(Sno, Sname, Grade)
AS 
SELECT Student.Sno, Sname, Grade 
FROM Student, SC
WHERE Sdept='IS' AND
	Student.Sno=SC.Sno AND 
	SC.Cno= '1';

基于视图的视图

  • 建立信息系选修了1号课程且成绩在90分以上的学生的视图
CREATE VIEW IS_S2
AS
SELECT Sno, Sname, Grade 
FROM  IS_S1
WHERE  Grade>=90;

带表达式的视图

  • 定义一个反映学生出生年份的视图
CREATE VIEW BT_S(Sno, Sname, Sbirth)
AS 
SELECT Sno, Sname, 2007-Sage 
FROM Student;

分组视图

  • 用带有聚集函数和 GROUP BY 子句的查询来定义视图

  • 将学生的学号及他的平均成绩定义为一个视图
// 由于AS子句中SELECT语句的目标列平均成绩是通过作用聚集函数得到的,
// 所以 CREATE VIEW中必须明确定义组成S_G视图的各个属性列名
CREATE VIEW S_G(Sno, Gavg)
AS  
SELECT Sno, AVG(Grade) FROM SC	// 假设SC表中“成绩”列Grade为数字型
GROUP BY Sno;

不指定属性列

  • 将 Student 表中所有女生记录定义为一个视图
CREATE VIEW F_Student(F_Sno, name, sex, age, dept)
AS
SELECT *
FROM  Student WHERE Ssex='女';
  • 缺点:修改基表 Student 的结构后,Student 表与 F_Student 视图的映象关系被破坏,导致该视图不能正确工作

删除视图

DROP  VIEW  <视图名> [CASCADE];
  • 该语句从数据字典中删除指定的视图定义; 如果该视图上还导出了其他视图,则必须使用 CASCADE 级联删除语句,把该视图和由它导出的所有视图一起删除
  • 基本表删除后,由该基本表导出的所有视图(定义)没有被删除,但均已无法使用了。因此,删除基表时,由该基表导出的所有视图定义都必须显式地使用 DROP VIEW 语句删除

查询视图

  • 用户角度:查询视图与查询基本表相同
  • RDBMS 实现视图查询的方法: 视图消解法(View Resolution)
    • 进行有效性检查,检查查询中涉及的表、视图等是否存在
    • 如果存在,则从数据字典中取出视图的定义,把定义中的子查询和用户的查询结合起来,转换成等价的对基本表的查询
    • 执行修正后的查询

  • 在信息系学生的视图中找出年龄小于20岁的学生
CREATE VIEW IS_Student 
AS 
SELECT Sno, Sname, Sage 
FROM Student
WHERE Sdept='IS';
SELECT  Sno, Sage 
FROM    IS_Student 
WHERE   Sage<20;
  • 视图消解转换后的查询语句为:
SELECT Sno, Sage
FROM   Student
WHERE  Sdept='IS' AND Sage<20;

  • 查询选修了1号课程的信息系学生
SELECT IS_Student.Sno, Sname
FROM   IS_Student, SC
WHERE  IS_Student.Sno = SC.Sno AND SC.Cno='1';

视图消解法的局限

  • 有些情况下,视图消解法不能生成正确查询

  • 在 S_G 视图中查询平均成绩在 90 分以上的学生学号和平均成绩
// S_G 视图的子查询定义
CREATE VIEW S_G (Sno,Gavg) 
AS
SELECT  Sno, AVG(Grade)
FROM  SC GROUP BY Sno;
SELECT * FROM S_G
WHERE Gavg>=90;
  • 将本例中的查询语句与定义 S_G 视图的子查询结合,形成下列查询语句
// 错误
SELECT Sno, AVG(Grade) 
FROM SC
WHERE AVG(Grade)>=90
GROUP BY Sno;
  • 这种情况应该直接对基本表进行查询;正确的查询语句如下:
SELECT Sno, AVG(Grade) 
FROM SC
GROUP BY Sno HAVING AVG(Grade)>=90;

更新视图

  • 对视图的更新操作也是通过视图消解,转换为对基本表的更新操作
  • 允许对行列子集视图进行更新,对其他类型视图的更新不同系统有不同限制:一些视图是不可更新的,因为对这些视图的更新不能唯一地有意义地转换成对相应基本表的更新
    • 例:视图 S_G 为不可更新视图
// 这个对视图的更新无法转换成对基本表SC的更新
UPDATE S_G
SET    Gavg = 90
WHERE  Sno ='200215121';

  • 将信息系学生视图 IS_Student 中学号 200215122 的学生姓名改为“刘辰”
UPDATE IS_Student
SET    Sname = '刘辰'
WHERE  Sno='200215122';
  • 转换后的语句:
UPDATE Student
SET    Sname= '刘辰'
WHERE  Sno= '200215122' AND Sdept= 'IS';

  • 向信息系学生视图 IS_S 中插入一个新的学生记录: 200215129,赵新,20岁
INSERT
INTO   IS_Student
VALUES ('95029', '赵新', 20);
  • 转换为对基本表的更新:
INSERT
INTO  Student(Sno, Sname, Sage, Sdept) 
VALUES ('200215129', '赵新', 20, 'IS');

  • 删除信息系学生视图 IS_Student 中学号为 200215129 的记录
DELETE
FROM  IS_Student
WHERE Sno='200215129';

视图的作用

  • 视图能够简化用户的操作,使用户可以将注意力集中在他所关心的数据上
  • 视图使用户能以多种角度看待同一数据,适当的利用视图可以更清晰的表达查询
  • 视图对重构数据库提供了一定程度的逻辑独立性
  • 视图能够对机密数据提供安全保护

猜你喜欢

转载自blog.csdn.net/weixin_42437114/article/details/115096374