数据库基础(基本概念、关系数据库、数据库标准语言SQL)

数据库基础

绪论

数据库系统概述

4个基本概念

  1. 数据(data)

    定义:描述事物的符号。数据的含义称为数据的雨衣,数据与其语义是密不可分的。

  2. 数据库(DataBase,DB)

    定义:数据库是长期存储在计算机内、有组织的、可共享的大量数据的集合。数据库中的数据按一定的数据模型组织、描述和存储,具有较小的冗余度、较高的数据独立性和易扩展性,并可为各种用户共享。

    总之,数据库数据具有永久存储、有组织和可共享三个基本特点

  3. 数据库管理系统(DataBase Management System,DBMS)

    是计算机的基础软件。有数据定义功能;数据组织、存储和管理功能、数据操纵功能、数据库的建立和维护功能以及其他的一些功能。

  4. 数据库系统(DataBase System,DBS)

    是由数据库、数据库管理系统、应用程序和数据库管理员组成的存储、管理、处理和维护数据的系统。

数据管理技术的产生和发展的三个阶段

人工管理阶段 文件系统阶段 数据库系统阶段
应用背景 科学计算 科学计算、数据管理 大规模数据管理
硬件背景 无直接存取存储设备 磁盘、磁鼓 大容量磁盘、磁盘阵列
软件背景 没有操作系统 有文件系统 有数据库管理系统
处理方式 批处理 联机实时处理、批处理 联机实时处理、分布处理、批处理
数据的管理者 用户(程序员) 文件系统 数据库管理系统
数据面向的对象 某一应用程序 某一应用 现实世界(一个部门、企业、跨国组织等)
数据的共享程度 无共享、冗余度极大 共享性差、冗余度大 共享性高、冗余度小
数据的独立性 不独立、完全依赖于程序 独立性差 具有高度的物理独立性和一定的逻辑独立性
数据的结构化 无结构 记录内有结构、整体无结构 整体结构化,用数据模型描述
数据控制能力 应用程序自己控制 应用程序自己控制 由数据库管理系统提供数据安全性、完整性、并发控制的恢复能力

与人工管理和文件系统相比较,数据库系统的特点主要有以下几个方面。

  1. 数据结构化

    数据库系统实现整体数据的结构化,这是数据库的主要特征之一,也是数据库系统与文件系统的本质区别。

    所谓整体结构化是指数据库中的数据不再仅仅针对某一个应用,而是面向整个组织或企业;不仅数据内部是结构化的,而且整体是结构化的,数据之间是具有联系的。

  2. 数据的共享性高、冗余度低且易扩充

    数据共享可以大大减少数据冗余,节约存储空间。数据共享还能避免数据之间的不相容与不一致性。这使得数据库系统弹性大,易于扩充。

  3. 数据的独立性高

    包括物理独立性和逻辑独立性。

    物理独立性是值用户的应用程序与数据库中数据的物理存储时相互独立的。

    逻辑独立性是指用户的应用程序与数据库的逻辑结构是相互独立的。

  4. 数据由数据库管理系统统一管理和控制

    数据库的安全性是指保护数据以防止不合法使用造成的数据泄密和破坏。

    数据的完整性是指数据的正确性、有效性和相容性。

综上所述,数据库是长期存储在计算机内有组织、大量、共享的数据集合。它可以供各种用户共享,具有最小冗余度和较高的数据独立性。数据库管理系统在数据库建立、运用和维护时对数据库进行统一控制,以保证数据的完整性和安全性,并在多用户同时使用数据库时进行并发控制,在发生故障后对数据库进行恢复。

从以加工数据的程序为中心转向围绕共享的数据库位中心的新阶段。

数据模型

是对现实世界数据特征的抽象

数据模型是数据库系统的核心和基础

概念模型

主要用于数据库设计

实体:客观存在并可相互区别的事物称为实体。

属性:实体所具有的某一特性。

码:唯一标识实体的属性集。

实体型:用实体名及其属性名集合来抽象和刻画同类实体,称为实体型。

实体集

联系:实体之间的联系通常是指不同实体集之间的联系。

​ 实体间的联系有一对一、一对多和多对多等多种类型。

实体-联系方法,该方法用E-R图来描述现实世界的概念模型,E-R方法也称为E-R模型。

逻辑模型

包括层次模型、网状模型、关系模型、面向对象数据模型和对象关系数据模型、半结构化数据模型等

主要用于数据库管理系统的实现

首先将现实世界抽象为信息世界,然后将信息世界转换为机器世界

数据模型的组成要素

数据结构、数据操作和数据的完整性约束条件。

数据结构描述数据库的组成对象以及对象之间的联系。

数据操作是指对数据库中各种对象的实例允许执行的操作的集合,包括操作及有关的操作规则。

数据的完整性约束条件是一组完整性规则,完整性规则是给定的数据模型中数据及其联系所具有的制约和依存规则。

层次模型

是数据库系统中最早出现的数据模型。用树形结构来表示各类实体以及实体间的联系。

数据结构

  1. 有且仅有一个结点没有双亲结点,这个结点称为根节点;
  2. 根以外的其他结点有且仅有一个双亲结点。

层次模型像一颗倒立的树,结点的双亲是唯一的。

网状模型

典型代表是DBTG系统。

数据结构

  1. 允许一个以上的结点无双亲。
  2. 一个结点可以有多于一个的双亲。

层次模型中子女结点与双亲结点的联系是唯一的,而在网状模型中这种联系可以不唯一。

关系模型

数据结构

关系:一个关系对应通常说的一张表

元组:表中的一行即为一个元组

属性:表中的一列即为一个属性,给每一个属性起一个名称即属性名。

码:也成为码键。表中的某个属性组,它可以唯一确定一个元组。

域:是一组具有相同数据结构的值的类型。属性的取值范围来自某个域。

分量:元组中的一个属性值。

关系模式:对一般关系的描述,一般表示为 关系名(属性1,属性2,…,属性n)

关系模型要求关系必须是规范化的,关系的每一个分量必须是一个不可分的数据项。也就是说,不允许表中还有表。

数据操纵

关系模型中的数据操作是集合操作,操作对象和操作结果都是关系。

关系模型把存取路径向用户隐蔽起来,用户只要指出干什么或怎么干,不必详细说明怎么干或怎么找,从而大大提高了数据的独立性。

数据库系统的结构

数据库系统模式的概念

型(type)是指对某一类数据的结构和属性的说明,值(value)是型的一个具体赋值。

模式是数据库中全体数据的逻辑结构和特征的描述,仅仅设计型的描述。

模式是相对稳定的,而实例是相对变动的。

数据库系统的三级模式结构

是指数据库系统是由外模式、模式和内模式三级构成。

  1. 模式

    也称逻辑模式,是数据库中全体数据的逻辑结构和特征的描述,是所有用户的公共数据视图。是数据库系统模式结构的中间层,不涉及数据的物理存储细节和硬件环境。一个数据库只有一个模式。数据库管理系统提供模式数据定义语言(DDL)来严格定义模式。

  2. 外模式

    也称子模式或用户模式,它是数据库用户能够看见和使用的局部数据的逻辑结构和特征的描述,是数据库用户的数据视图,是与某一应用有关的数据的逻辑表示。外模式通常是模式的子集。一个数据库可以有多个外模式,另外,同一外模式也可以为某一个用户的多个应用系统所使用,但一个应用程序只能使用一个外模式。数据库管理系统提供外模式数据定义语言(外模式DDL)来严格定义外模式。

  3. 内模式

    也称存储模式,一个数据库只能有一个内模式。它是数据物理结构存储方式的描述,是数据在数据库内部的组织方法。

数据库的二级映像功能与数据独立性

保证了数据库系统中的数据能够具有较高的逻辑独立性和物理独立性。

  1. 外模式/模式映像

    当模式改变时,由数据库管理员对各个外模式/模式的映像做相应改变,可以使外模式保存不变。应用程序是依据数据的外模式编写的,从而应用程序不必修改,保证了数据与程序的逻辑独立性,简称数据的逻辑独立性。

  2. 模式/内模式映像

    当数据库的存储结构改变时,由数据库管理员对模式/内模式映像作相应改变,可以使模式保存不变,从而应用程序也不必改变。保证了数据与程序的物理独立性,简称数据的物理独立性。

数据与程序之间的独立性使得数据的定义和描述可以从应用程序中分离出去。另外由于数据的存取由数据库管理系统管理,从而简化了应用程序的编制,大大减少了应用程序的维护和修改。

数据库系统的组成

  1. 硬件平台及数据库
  2. 软件
  3. 人员

关系数据库

关系数据库结构及其形式化定义

关系

  1. 域是一组具有相同数据结构的值的集合

  2. 笛卡尔积

    是域上的一种集合运算

    给定一组域D1,D2,…,Dn,允许其中某些域是相同的,D1,D2,…,Dn的笛卡尔积为:{(d1,d2,…,dn)},其中,每一个元素(d1,d2,…,dn)叫做一个n元组,或简称元组。元素中的每一个值di叫做一个分量。

    一个域允许的不同取值个数称为这个域的基数。(每个集合中元素个数的乘积

  3. 关系

    • 笛卡尔积的子集叫做在域D1,D2,…,Dn上的关系,表示为R(D1,D2,…,Dn),这里R表示关系的名字,n是关系的目或度。

    • 关系中的每个元素是关系中的元组,通常用t表示。

      当n=1时,称该关系为单元关系,或一元关系。

      当n=2时,成该关系为二元关系。

    • 关系时笛卡尔积的有限子集,所以关系也是一张二维表。

    • 若关系中的某一属性的值能唯一标识一个元组,而其子集不能,则称该属性组为候选码。

    • 若一个关系有多个候选码,则选定其中一个为主码。

    • 候选码的诸属性称为主属性。不包含在任何候选码中的属性称为非主属性或非码属性。

    • 关系可以有三种类型:基本关系(通常又称为基本表或基表)、查询表和视图表。

    • 基本关系具有6条性质:

      • 列是同质的,即每一列中的分量是同一类型的数据,来自同一个域。
      • 不同的列可出自同一个域。
      • 列的顺序无所谓
      • 任意两个元组的候选码不能取相同的值
      • 行的顺序无所谓
      • 分量必须取原子值
    • 关系模型要求关系的每一个分量必须是一个不可分的数据项。

关系模式

形象地表示为R(U,D,DOM,F),其中R为关系名,U为组成该关系的属性名集合,D为U中属性所来自的域,DOM为属性向域的映像集合,F为属性间数据的依赖关系集合。

关系数据库

在关系模型中,实体以及实体间的联系都是用关系来表示的。例如导师实体、研究生实体、导师与研究生之间的一对多联系都可以分别用一个关系来表示。在一个给定的应用领域中,所以关系的集合构成一个关系数据库。

关系数据库也有型和值之分。关系数据库的型也称为关系数据库模式,是对关系数据库的描述。

关系数据库的值是这些关系模式在某一时刻对应的关系的集合,通常就称为关系数据库。

关系操作

基本操作

查询、插入、删除、修改

查询操作又分为选择、投影、并、差、笛卡尔积5种基本操作。

关系操作的特点是集合操作,即操作的对象和结果都是集合。

关系数据语言的分类

分为关系代数和关系演算。

关系演算又可以分为元组关系演算和域关系演算。

此外还有一种介于关系代数和关系演算之间的结构化查询语言(SQL),这是集查询、数据定义语言、数据操纵语言和数据控制语言于一体的关系数据语言。

关系的完整性

实体完整性和参照完整性被称为是关系的两个不变性。

实体完整性

实体完整性规则:若属性(指一个或一组属性)A是基本关系R的主属性,则A不能取空值。所谓空值就是“不知道”或“无意义”的值。

参照完整性

设F是基本关系R的一个或一组属性,但不是关系的码,Ks是基本关系S的主码。如果F域Ks对应,则称F是R的外码,并称基本关系R为参照关系,基本关系S为被参照关系或目标关系

用户定义的完整性

反映某一具体应用涉及的数据必须满足的语义要求。

关系代数

用对关系的运算来表示查询,分为传统的集合运算和专门的关系运算两类。

传统的集合运算是二目运算,包括并、差、交、笛卡尔积4种运算。

这里不赘述。

专门的关系运算包括选择、投影、连接、除运算等。

  1. 选择

    从行的角度,从关系中选择元组。

  2. 投影

    从列的角度,选出若干属性列。

    会去重

  3. 连接

    是从两个关系的笛卡尔积中选取属性间满足一定条件的元组。

    • 等值连接

      选取两属性值相等的那些元组。

    • 自然连接

      要求两个关系中进行比较的分量必须是同名的属性组,并在结果中把重复的属性列去掉。

      在作自然连接时,这些被舍弃的元组被称为悬浮元组

    如果把悬浮元组也保存在结果中,而在其他属性上填空值(NULL),那么这种连接就叫做外连接。

    如果只保留左边关系中的悬浮元组就叫做左外连接,如果只保留右边关系中的悬浮元组就叫做右外连接。

  4. 设关系R除以关系S的结果为关系T,则T包含所有在R但不在S中的属性及其值,且T的元组与S的元组的所有组合都在R中。

    求解过程,先求出关系R的象集,再求出关系S与关系R共有属性的投影,观察R中的哪个象集包含了投影所有的元组,则这个集合即为结果。

注意关系带式表达式的求法

关系演算

关系数据库标准语言SQL

SQL概述

SQL功能:

  1. 数据查询

    SELECT

  2. 数据定义

    CREATE,DROP,ALTER

  3. 数据操纵

    INSERT,UPDATE,DELETE

  4. 数据控制

    GRANT,REVOKE

学生-课程数据库

首先定义一个学生-课程模式S-T,包括三个表。

  • 学生表:Student(Sno,Sname,Ssex,Sage,Sdept)
  • 课程表:Course(Cno,Cname,Cpno,Ccredit)
  • 学生学科表:SC(Sno,Cno,Grade)

关系的主码加下划线表示。

Student表

学号Sno 姓名Sname 性别Ssex 年龄Sage 所在系Sdept
201215121 李勇 20 CS
201215122 刘晨 19 CS
201215123 王敏 18 MA
201215125 张立 19 IS

Course表

课程号Cno 课程名Cname 先行课Cpno 学分Ccredit
1 数据库 5 4
2 数学 2
3 信息系统 1 4
4 操作系统 6 3
5 数据结构 7 4
6 数据处理 2
7 PASCAL语言 6 4

SC表

学号Sno 课程号Cno 成绩Grade
201215121 1 92
201215121 2 85
201215121 3 88
201215122 2 90
201215122 3 80

数据定义

包括模式定义、表定义、视图和索引的定义。

一个关系数据库管理系统的实例中可以建立多个数据库,一个数据库中可以建立多个模式,一个模式下通常包括多个视图索引等数据库对象。

模式的定义和删除

模式定义语句:

CREATE SCHEMA <模式名> AUTHORIZATION <用户名>

要想创建模式,调用该命令的用户必须拥有数据库管理员权限,或者获得了数据库管理员授予的CREATE SCHEMA 的权限。

定义模式实际上定义了一个命名空间,在这个空间中可以进一步定义该模式包含的数据库对象,例如基本表、视图、索引等。

删除模式:

DROP SCHEMA <模式名><CASCADE|RESTRICT>

选择CASCADE(级联),表示在删除模式的同时把该模式中数据库对象全部删除;

选择RESTRICT(限制),表示如果该模式中已经定义了下属的数据库对象(如表、视图等),则拒绝该删除语句的执行。只有当该模式中没有任何下属的对象时才能执行DROP SCHEMA语句。

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

定义的基本格式:

CREATE TABLE <表名>(<列名><数据类型>[列级完整性约束条件]
					[,<列名><数据类型>[列级完整性约束条件]]
					...
					[,<表级完整性约束条件>]);

demo:建立一个“学生”表Student。

CREATE TABLE Student
    (Sno CHAR(9)) PRIMARY KEY,//主键
    Sname CHAR(20) UNIQUE,//唯一性
    Ssex CHAR(2),
    Sage SMALLINT,
    Sdapt CHAR(20)
    );

demo:建立一个“课程”表Course

CREATE TABLE Course
	(Cno CHAR(4) PRIMARY KEY,//主键
    Cname CHAR(40) NOT NULL,//不为空
    Cpno CHAR(4),//先选课
    Ccredit SMALLINT,
    FOREIGN KEY(Cpno) REFERENCES(Cno)//Cpno是外码,被参照表Course,被参照列是Cno
    );

参照表和被参照表可以是同一个表

demo:建立学生选课表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 Student(Cno)
    );

一个属性选用哪种数据类型要根据实际情况来决定,一般要从两个方面来考虑,一是取值范围,二是要做哪些运算。

当定义表的时候有3种方式定义其所属的模式。

  1. 在表名中明显地给出模式名。
  2. 在创建模式语句中同时创建表。
  3. 设置所属的模式,这样在创建表时表名中不必给出模式名。

修改表的基本格式:

ALTER TABLE <表名>

[ADD [COLUMN] <新列名><数据类型>[完整性约束]]

[ADD<表级完整性约束>]

[DROP [COLUMN] <列名> [CASCADE|RESTRICT]]

[DROP CONSTRAINT<完整性约束名> [RESTRICT|CASCADE]]

[ALTER COlUMN <列名><数据类型>];

删除表的基本格式:

DROP TABLE <表名> [RESTRICT|CASCADE]

索引的建立与删除

建立索引是加快查询速度的有效手段。

常见索引包括顺序文件上的索引、B+树索引、散列索引、位图索引等。

  • 顺序文件上的索引是针对按指定属性值升序或降序存储的关系,在属性上建立一个顺序索引文件,索引文件由属性值和相应的元组指针组成。

  • B+树索引是将索引属性组织成B+树形式,B+树的叶结点为属性值和相应的元组指针。具有动态平衡的特点。

  • 散列索引是建立若干个桶,将索引属性按照其散列函数值映射到桶中,桶中存放索引属性值和相应的元组指针。具有查找速度快的特点。

  • 位图索引是用位向量记录索引属性中可能出现的值,每一个位向量对应一个可能值。

建立索引:

CREATE [UNIQUE][CLUSTER] INDEX <索引名>
ON <表名>(<列名> [<次序>][,<列名>[<次序>]]...);

其中,每个列名后面还可以用次序指定索引值的排列次序,可选ASC(升序)或DESC(降序),默认值为ASC。

UNIQUE表明此索引的每一个索引值只对应唯一的数据记录。

CLUSTER表示要建立的所有是聚簇索引。

demo:为学生-课程数据库中的Student、Course和SC三个表建立索引。其中Student表按学号升序建唯一索引,Course表按课程号升序建唯一索引,Sc表按学号和课程号建唯一索引。

CREATE UNIQUE INDEX Stusno ON Student(Sno);
CREATE UNIQUE INDEX COUcno ON Couse(Cno);
CREATE UNIQUE INDEX SCno ON SC(Sno ASC,Cnp DESC);

修改索引:

一般格式:

ALTER INDEX <旧索引名> RENAME TO <新索引名>;

demo:将SC表的SCno索引名修改为SCSno

ALTER INDEX SCno RENAME TO SCSno;

删除索引:

一般格式:

DROP INDEX <索引名>

demo:删除Student表的Stusname索引

DROP INDEX Stusname;

数据字典

数据字典是关系数据库管理系统内部的一组系统表,它记录了数据库中所有的定义信息。

数据查询

一般格式:

SELECT [ALL|DISTINCT] <目标列表达式>[,<目标列表达式>]...
FROM <表名或视图名> [,<表名或视图名>...]|(<SELECT语句>)[AS]<别名>
[WHERE <条件表达式>]
[GROUP BY <列名1> [HAVING <条件表达式>]]
[ORDER BY <列名2> [ASC|DESC]];

整个SELECT语句的含义是,根据WHERE子句的条件表达式从FROM子句指定的基本表、视图或派生表中找出满足条件的元组,再按SELECT子句中的目标列表达式选出元组中的属性值形成结果表。

如果有GROUP BY子句,则将结果按<列名1>的值进行分组,该属性列值相等的元组为一个组。通常会在每组中作用聚集函数。如果GROUP BY子句带HAVING短语,则只有满足指定条件的组才予以输出。

如果有ORDER BY子句,则结果表还要按<列名2>的值的升序或降序排序。

单表查询

选择表中的若干列:即为关系代数的投影运算。

SELECT子句的<目标表达式>

demo:查询全体学生的学号和姓名

SELECT Sno,Sname FROM Student;

demo:查询全体学生的详细记录

SELECT * FROM Student;

查询经过计算的值

demo:查询全体学生的姓名及其出生年份

SELECT Sname,2022-Sage FROM Student;

目标表达式不仅可以是算术表达式,还可以是字符串常量、函数等

demo:查询全体学生的姓名、出生年份和所在的院系,要求用小写字母表示系名。

SELECT Sname,'Year of Birth:',2022-Sage,LOWER(Sdept) FROM Student;

demo:给上述列指定别名

SELECT Sname,'Year of Birth:',2022-Sage BIRTHDAY,LOWER(Sdept) DEPARTMENT FROM Student;

选择表中的若干元组

消除重复行:指定DISTINCT。若没指定,默认为ALL。

demo:查询选修了课程的学生号

SELECT DISTINCT Sno FROM SC;

查询满足条件的元组:通过WHERE子句来实现。

查询条件 谓词
比较 =,>,<,>=,<=,!=,<>,!<,!>;NOT + 上述比较运算符
确定范围 BETWEEN AND,NOT BETWEEN AND
确定集合 IN,NOT IN
字符匹配 LIKE,NOT LIKE
空值 IS NULL,IS NOT NULL
多重条件 AND,OR,NOT

demo:查询计算机科学系全体学生名单

SELECT Sname FROM Student WHERE Sdept='CS';

ps:由于一般学校学生基数大,可以在Student表的Sdept列上建立索引,系统会利用该索引找出Sdept=’CS‘的元组,从中取出Sname列值形成结果关系。这就避免了对Student表的全局扫描,加快了查询速度。

demo:查询年龄在20~30岁之间的学生的姓名、系别和年龄。

SELECT Sname,Sdept,Sage FROM Student WHERE Sage BETWEEN 20 ADN 30;

demo:查询年龄不在20~30岁之间的学生的姓名、系别和年龄。

SELECT Sname,Sdept,Sage FROM Student WHERE Sage NOT BETWEEN 20 ADN 30;

demo:查询计算机系(CS)、数学系(MA)和信息系(IS)学生的姓名和性别。

SELECT Sname,Ssex FROM Student WHERE Sdept IN ('CS','MA','IS');

字符匹配:谓词LIKE可以用来进行字符串的匹配。其一般语法格式如下:

[NOT] LIKE '<匹配串>' [ESCAPE'<换码字符>']

其含义是查找指定的属性列值与<匹配串>相匹配的元组。匹配串可以是一个完整的字符串,也可以是含有通配符%和_。

其中:%(百分号)代表任意长度(可以为0)的字符串。例如a%b表示以a开头,b结尾的任意长度的字符串。如acb、addgb、ab等都满足该匹配串。

_(下划线)代表任意单个字符。例如a_b代表以a开头,以b结尾的长度为3的任意字符串。如acb、afb等都满足匹配串。

demo:查询学号为201215121的学生的详细情况。

SELECT * FROM Student WHERE Sno LIKE '201215121';

等价于

SELECT * FROM Student WHERE Sno='201215121';

如果LIKE后面不含通配符,则可以用=运算符取代LIKE谓词,用!=或<>运算符取代NOT LIKE谓词。

demo:查询所有姓刘的学生的姓名、学号和性别。

SELECT Sname,Sno,Ssex FROM Student WHERE Sname LIKE '刘%';

demo:查询姓欧阳且全名为三个字的学生的姓名

SELECT Sname FROM Student WHERE Sname LIKE '欧阳_';

注意:如果用户要查询的字符串本身就含有通配符%或_,这时候就要使用ESCAPE '<换码字符>'短语对通配符进行转义了。

demo:查询DB_Design课程的课程号和学分

SELECT Cno,Ccredit FROM Course WHERE Cname LIKE 'DB\_Design' ESCAPE'\';

demo:查询"以DB_"开头且倒是第三个字符为i的课程的详细情况

SELECT * FROM Course WHERE Cname LIKE 'DB\_%i__'ESCAPE'\';

demo:查询选修了3号课程的学生的学号及其成绩,查询结果按分数的降序排列

SELECT Sno,Grade FROM SC WHERE Cno='3' ORDER BY Grade DESC;

对于空值,排序时显示的次序由具体系统实现来决定。例如按升序排,含空值的元组最后显示;按降序排,空值的元组则最先显示。

demo:查询全体学生情况,查询结果按所在系的系号升序排列,同一系中的学生按年龄降序排列。

SELECT * FROM Student ORDER BY Sdept,Sage DESC;

聚集函数

函数 说明
COUNT(*) 统计元组个数
COUNT([DISTINCT|ALL]<列名>) 统计一列中值的个数
SUM([DISTINCT|ALL]<列名>) 计算一列值的总和
AVG([DISTINCT|ALL]<列名>) 计算一列值的平均值
MAX([DISTINCT|ALL]<列名>) 求一列值中的最大值
MIN([DISTINCT|ALL]<列名>) 求一列值中的最小值

如果指定DISTINCT短语,则表示在计算时去重。

注意:WHERE子句中是不能用聚集函数作为条件表达式的。聚集函数只能用于SELECT子句和GROUP BY中的HAVING子句。

GROUP BY子句将查询结果按某一列或多列的值分组,值相等的为一组。分组后聚集函数将作用于每一个组,即每一组都有一个函数值。

demo:求各个课程号及相应的选课人数。

SELECT Cno,COUNT(Sno) FROM SC GROUP BY Cno;

如果分组后还要求按一定的条件对这些组进行筛选,最终只输出满足指定条件的组,则可以使用HAVING短语指定筛选对象。

demo:查询选修了三门以上课程的学生学号

SELECT Sno FROM SC GROUP BY Sno HAVING COUNT(*)>3

demo:查询平均成绩大于等于90分的学生学号和平均成绩。

SELECT Sno,AVG(Grade) FROM SC GROUP BY Sno HAVING AVG(Grade)>=90;

连接查询

等值与非等值连接查询

demo:查询每个学生及其选修课程的情况

SELECT Student.*,SC.* FROM Student,SC WHERE Student.Sno=SC.Sno;

执行的过程是:首先在表Student中找到第一个元组,然后从头开始扫描SC表,逐一查找与Student第一个元组的Sno相等的SC元组,找到后就将Student表中的第一个元组与该元组拼接起来,形成结果表中的一个元组。SC表全部查完后,再找Student中第二个元组,然后再从头开始扫描SC,逐一查找满足连接条件的元组,找到后就将Student表中的第二个元组与该元组拼接起来,形成结果表中的一个元组。重复上述操作,知道Student表中的全部元组都处理完毕为止。这就是嵌套循环连接算法的思想。

可以参考一下笛卡尔积的思想。

如果在SC表Sno上建立了索引的话,就不用每次全表扫描SC表了,而是根据Sno值通过索引找到相应的SC元组。用索引查询SC中满足条件的元组一般会比全表扫描快。

若在等值连接中把目标列中重复的属性列去掉则为自然连接。

demo:对上一个demo用自然连接完成

SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade FROM Student,SC WHERE Student.Sno=SC.Sno;

也可以用一条SQL语句同时完成选择和连接查询,这时WHERE子句是由连接谓词和选择谓词组成的复合条件。

demo:查询选修2号课程且成绩在90分以上的所有学生的学号和姓名。

SELECT Student.Sno,Sname FROM Student,SC WHERE Student.Sno=SC.Sno AND SC.Cno='2' AND SC.Grade>90;

自身连接

demo:查询每一门课的间接先修课(即先修课的先修课)

可以为Course表取两个别名,FIRST和SECOND

SELECT FIRST.Cno,SECOND.Cpno FROM Course FIRST,Course SECOND WHERE FIRST.Cpno=SECOND.Cno;

外连接

仍把前一个表的悬浮元组保存在结果关系中,后一个表的值为NULL。

demo:

SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade FROM Student LEFT OUTER JOIN SC ON (Student.Sno=Sc.Sno);

多表连接

demo:查询每个学生的学号、姓名、选修的课程名及成绩。

SELECT Student.Sno,Sname,Cname,Grade FROM Student,Course,Sc WHERE Student.Sno=SC.Sno AND Course.Cno=SC.Cno;

嵌套查询

注意:子查询的SELECT语句中不能使用ORDER BY子句,ORDER BY子句只能对最终的查询结果排序

带有IN谓词的子查询:

demo:查询与“刘晨”在同一个系学习的学生

怎么做?先分步来完成此查询,然后再构造嵌套查询。

SELECT Sno,Sname,Sdept FROM Student WHERE Sdept IN (SELECT Sdept FROM Student WHERE Sname = '刘晨');

本例中子查询的查询条件不依赖于父查询,称为不相关子查询。

demo:查询选修了课程名为“信息系统”的学生学号和姓名

怎么做?先在Course中找出信息系统的课程号,再根据课程号在SC表中找出选修了该课程的学生学号,再根据学号在Student表中找出姓名。

SELECT Sno,Sname 
From Student 
WHERE Sno IN
	(SELECT Sno
     FROM SC
     WHERE Cno IN
     	(SELECT Cno
         FROM Course
         WHERE Cname='信息系统'
        )
    );

本例也是一个不相关子查询。

带有比较运算符的子查询:

demo:找出每个学生超过他自己选修课程平均成绩的课程号

SELECT Sno,Cno
FROM SC x
WHERE Grade>=(SELECT AVG(Grade)
             FROM SC y
             WHERE y.Sno = x.Sno);

x是表SC的别名,又称为元组变量,可以用来表示SC的一个元组。

内层查询是求一个学生所有选修课程的平均成绩,至于是哪个学生的平均成绩要看参数x.Sno的值,而该值是与父查询相关的,因此这类查询称为相关子查询。

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

demo:查询非计算机科学系中比计算机科学系任意一个学生年龄小的学生姓名和年龄

SELECT Sname,Sage
FROM Student
WHERE Sage<ANY(SELECT Sage
              FROM Student
              WHERE Sdept='CS')
AND Sdept<>'CS';

demo:查询非计算机科学系中比计算机科学系所有学生年龄都小的学生姓名及年龄。

SELECT Sname,Sage
FROM Student
WHERE Sage<ALL(SELECT Sage
              FROM Student
              WHERE sdept='CS')
AND Sdept<>'CS';

以上两例同样能用聚合函数实现

= <>或!= < <= > >=
ANY IN <=MAX >MIN >=MIN
ALL NOT INI <=MIN >MAX >=MAX

带有EXISTS谓词的子查询

不返回任何数据,只产生逻辑值“true”或“false”。

demo:查询所有选修了 1号课程的学生姓名。

SELECT Sname
FROM Student,SC
WHERE Student.Sno=SC.Sno AND Cno='1';

可以在Student中依次取每个元组的Sno值,用此值取检查SC表。若SC中存在这样的元组,其Sno值等于此Student.Sno值,并且其Cno=‘1’,则取此Student.Sname送入结果表:

SELECT Sname
FROM Student
WHERE EXISTS
	(SELECT*
     FROM SC
     WHERE Sno=Student.Sno AND Cno='1';
    )

使用存在量词EXISTS后,若内层查询结果为空,则外层的WHERE子句返回真值,否则返回假值。

由EXISTS引出的子查询,其目标列表达式通常都用*,因为带EXISTS的子查询只返回真值或假值,给出列名无实际意义。

demo:查询选修了全部课程的学生姓名(也就是没有一门课程是他不选修的)

SELECT Sname
FROM Student
WHERE NOT EXISTS
	(SELECT *
    FROM Course
    WHERE NOT EXISTS
    	(SELECT *
        FROM SC
        WHERE Sno=Student.Sno
        	AND Cno=Course.Cno));

demo:查询至少选修了学生201215122选修的全部课程的学生号码(不存在这样的课程y,学生201215122选修了y,而学生x没有选)

SELECT DISTINCT Sno
FROM SC SCX
WHERE NOT EXISTS
	(SELECT *
    FROM SC SCY
    WHERE SCY.Sno='201215122' AND
    	NOT EXISTS
    	(SELECT *
        FROM SC SCZ
        WHERE SCZ.Sno=SCX.Sno AND
        	  SCZ.Cno=SCY.Cno));

集合查询

主要包括并操作UNION、交操作INTERSECT和差操作EXCEPT。

注意,参加集合操作的各查询结果的列数必须相同;对应项的数据类型也必须相同。

demo:查询计算机科学系的学生及年龄不大于19岁的学生。(并集)

SELECT *
FROM Student
WHERE Sdept='CS'
UNION
SELECT *
FROM Student
WHERE Sage<=19;

demo:查询计算机科学系的学生与年龄不大于19岁的学生的交集

SELECT *
FROM Student
WHERE Sdept='CS'
INTERSECT
SELECT *
FROM Student
WHERE Sage<=19;

demo:查询计算机科学系与年龄不大于19岁的学生的差集。

SELECT *
FROM Student
WHERE Sdept='CS'
EXCEPT
SELECT *
FROM Student
WHERE Sage<=19;

基于派生表的查询

子查询不仅可以出现在WHERE子句中,还可以出现在FROM子句中,这时子查询生成的临时派生表成为主查询的查询对象。

SELECT Sno,Cno
FROM SC,(SELECT Sno,Avg(Grade) FROM SC GROUP BY Sno)
		AS Avg_sc(avg_sno,avg_grade)
		WHERE SC.Sno=Avg_sc.avg_sno and SC.Grade >= Avg_sc.avg_grade

这里的FROM子句中的子查询将生成一个派生表Avg_sc。该表由avg_sno和avg_grade两个属性组成,记录了每个学生的学号及平均成绩。

主查询将SC表与Avg_sc按学号相等进行连接

需要说明的是,通过FROM子句生成派生表时,AS关键字可以省略,但必须为派生关系指定一个别名。

数据更新

插入数据

插入元组

INSERT 
INTO <表名> [<属性列1>[,<属性列2>]...]
VLAUES(<常量1>[,<常量2>]...);

demo:将一个新学生元组(学号:201215128,姓名:陈冬,性别:男,所在系:IS,年龄:18岁)插入到Student表中。

INSERT
INTO Student(Sno,Sname,Ssex,Sdept,Sage)
VALUES('201215128','陈冬','男','IS',18)

注意:字符串要用单引号(英文符号)括起来

demo:将学生张成民的信息插入到Student表中。

INSERT
INTO Student
VALUES('201215126','张成民','男',18,'CS')

注意这个例子只给出了表名,而没有给出属性名。所以值要与属性列一一对应。

插入子查询结果

语句格式:

INSERT
INTO <表名> [(<属性列1>[,<属性列2>...])]
子查询;

demo:对每一个系,求学生的平均年龄,并把结果存入数据库

首先在数据库中建立新表,其中一列存放系名,另一列存放相应的学生平均年龄

CREATE TABLE Dept_age
	(Sdept CHAR(15)
    Avg_age SMALLINT);

然后对Student表按系分组求平均年龄,再把系名和平均年龄存入新表中。

INSERT
INTO Dept_age(Sdept,Avg_age)
SELECT Sdept,AVG(Sage)
FROM Student
GROUP BY Sdept;

修改数据

一般格式:

UPDATE <表名>
SET <列名>=<表达式> [,<列名>=<表达式>]...
[WHERE <条件>];

修改一个元组:

UPDATE Student
SET Sage=22
WHERE Sno='201215121';

修改多个元组:

UPDATE Student
SET Sage=Sage+1;

带子查询的修改语句

UPDATE SC
SET Grade=0
WHERE Sno IN
	(SELECT Sno
    FROM Student
    WHERE Sdept='CS');

删除数据

一般格式:

DELETE
FROM <表名>
[WHERE<条件>];

注意:DELETE语句删除的是表中的数据,而不是关于表的定义

删除某一个元组:

DELETE
FROM Student
WHERE Sno='201215128';

删除多个元组的值:

DELETE 
FROM SC;

带子查询的删除语句:

DELETE
FROM SC
WHERE Sno IN
	(SELECT Sno
    FROM Student
    WHERE Sdept='CS');

空值的处理

产生

在插入语句中没有赋值的属性,其值为空值。外连接也会产生空值。空值的关系运算也会产生空值。

判断

用IS NULL或IS NOT NULL来表示

demo:从Student表中找出漏填了数据的学生信息。

SELECT *
FROM Student
WHERE Sname IS NULL OR Ssex IS NULL OR Sage IS NULL OR Sdept IS NULL;

空值的约束条件

属性定义中有NOT NULL约束条件的不能取空值,加了UNIQUE限制的属性不能取空值,码属性不能取空值。

空值的算术运算、比较运算和逻辑运算

demo:选出选修1号课程的不及格的学生以及缺考的学生

SELECT Sno
FROM SC
WHERE Cno='1' AND (Grade<60 OR Grade IS NULL);

视图

视图是从一个或几个基本表(或视图)导出的表。它与基本表不同,是一个虚表。数据库中只存放视图的定义,而不存放视图对应的数据,这些数据仍存放在原来的基本表中。

定义视图

建立视图:

CREATE VIEW <视图名> [(<列名>[,<列名>])]
AS <子查询>
[WITH CHECK OPTION];

demo:建立信息系学生的视图

CREATE VIEW IS_STUDENT
AS
SELECT Sno,Sname,Sage
FROM Student
WHERE Sdept='IS';

注意在系统执行CREATE VIEW语句的结果只是把视图的定义存入数据字典,并不执行其中的SELECT语句。

demo:建立信息系学生的视图,并要求进行修改和插入操作时仍需保证该视图只有信息系的学生。

CREATE VIEW IS_STUDENT
AS
SELECT Sno,Sname,Sage
FROM Student
WHERE Sdept='IS';
WITH CHECK OPTION;

这样以后对该视图进行插入、修改和删除操作时,关系数据库系统会自动加上Sdept='IS’的条件。

若一个视图是从单个基本表导出的,并且只是去掉了基本表的某些行和某些列,但保留了主码,则称这类视图为行列子集视图。上述视图就是一个行列自己视图。

demo:建立信息系选修了1号课程的学生的视图(包括学号、姓名、成绩)

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';

视图不仅可以建立在一个或多个基本表上,也可以建立在一个或多个已定义好的视图上,或建立在基本表与视图上。

demo:建立信息系选修了1号课程且成绩在90分以上的学生的视图。

CREATE VIEW IS_S2
AS
SELECT Sno,Sname,Grade
FROM IS_S1
WHERE Grade>=90;

由于视图中的数据并不实际存储,所以定义视图时可以根据应用的需要设置一些派生属性列。这些派生属性列由于在应用表中并不实际存在,也称它们为虚拟列。带虚拟列的视图也称为带表达式的视图。

demo:定义一个反映学生出生年份的视图

CREATE VIEW BT_S(Sno,Sname,Sbirth)
AS
SELECT Sno,Sname,2014-Sage
FROM Student;

这是一个带表达式的视图。视图中的出生年份值是通过计算得到的。

还可以用带有聚集函数和GROUP BY子句的查询来定义视图,这种视图称为分组视图

demo:将学生的学号及平均成绩定义为一个视图

CREATE VIEW S_G(Sno,Gavg)
AS
SELECT Sno,AVG(Grade)
FROM SC
GROUP BY Sno;

注意:由于AS子句中SELECT语句的目标列平均成绩是通过作用聚集函数得到的,所以CREATE VIEW中必须明确定义组成S_G视图的各个属性列名。S_G是一个分组视图

demo:将Student表中所有女生记录定义为一个视图

CREATE VIEW F_Student(F_Sno,name,sex,age,dept)
AS
SELECT *
FROM Student
WHERE Ssex='女';

注意:这里视图F_Student是由子查询SELECT *建立的。F_Student视图的属性列与Student表的属性列一一对应。如果以后修改了基本表Student的结构,则Student表与F_Student视图的映像关系就会被破坏。

删除视图

格式:

DROP VIEW <视图名> [CASCADE];

注意:基本表删除后,由该基本表导出的所有视图均无法正常使用了,但是视图的定义没有从字典中清除。删除这些视图定义需要显示地使用DROP VIEW语句。

查询视图

demo:在信息系学生的视图中找出年龄小于20岁的学生。

SELECT Sno,Sage
FROM IS_Student
WHERE Sage<20;

视图消解:从数据字典中取出视图的定义,把定义中的子查询和用户的查询结合起来,转换成等价的对基本表的查询,然后再执行修正了的查询。

demo:查询选修了1号课程的信息系的学生

SELECT IS_Student.Sno,Sname
FROM IS_Student,SC
WHERE IS_Student.Sno=SC.Sno AND SC.Cno='1';

更新视图

由于视图是不实际存储数据的虚表,因此对视图的更新最终转换为对基本表的更新。

为了防止对不属于视图范围内的基本表数据进行操作,可在定义视图时加上WITH CHECK OPTION子句。这样在视图上增、删、改数据时,关系数据库管理系统会检查视图定义中的条件,若不满足条件则拒绝执行该操作。

demo:将信息系学生视图IS_Student中学号为“201215122”的学生姓名改为“刘晨”

UPDATE IS_Student
SET Sname='刘晨'
WHERE Sno='201215122';

转换后的更新语句为:

UPDATE Student
SET Sname='刘晨'
WHERE Sno='201215122' AND Sdept='IS';

demo:向信息系学生视图IS_Student中插入一个新的学生记录,其中学号为"201215129",姓名为“赵新”,年龄为20岁

INSERT
INTO IS_Student
VALUES('201215129','赵新',20);

转换后的语句为:

INSERT
INTO Student(Sno,Sname,Sage,Sdept)
VALUES('201215129','赵新',20,'IS');

demo:删除信息系学生视图IS_Student中学号为“201215129”的记录

DELETE
FROM IS_Student
WHERE Sno='201215129';

转换后的语句为:

DELETE
FROM Student
WHERE Sno='201215129' AND Sdept='IS';

注意:并不是所有视图都可以更新的。

一般的,行列子集视图时可更新的。

  1. 若视图是由两个以上的基本表导出的在,则此视图不允许更新
  2. 若视图的字段来自字段表达式或常数,则不允许对此视图执行INSERT和UPDATE操作,但可以执行DELETE操作
  3. 若视图的字段来自聚集函数,则此视图不允许更新
  4. 若视图定义中含有GROUP BY子句,则此视图不允许更新。
  5. 若视图定义中含有DISTINCT短语,则此视图不允许更新。
  6. 若视图定义中含有嵌套查询,并且内层查询的FROM子句中设计的表也是导出该视图的定义表,则此视图不允许更新。

视图的作用

  1. 能够简化用户的操作
  2. 使用户能以多种角度看待同一数据
  3. 对重构数据库提供了一定程度的逻辑独立性
  4. 能够对机密数据提供安全保护
  5. 适当利用视图可以更清晰地表达查询

你可能感兴趣的:(数据库,sql,database)