写在前面的话

注意:本章非非非非非非非常的长,复习党只需要看3.3-3.6即可。

3.1 学生-课程数据库

学生-课程模式S-T :
学生表:Student(Sno,Sname,Ssex,Sage,Sdept)
课程表:Course(Cno,Cname,Cpno,Ccredit)
学生选课表:sc(Sno,Cno,Grade)
Student表

学号(Sno) 姓名(Sname) 性别(Ssex) 年龄(Sage) 所在系(Sdept)
200215121 李勇 20 CS
200215122 刘晨 19 CS
200215123 王敏 18 MA
200215125 张立 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)
200215121 1 92
200215121 2 85
200215121 3 88
200215122 2 90
200215122 3 80

这几张表要留个大概的印象,后面例题会用到。


3.2 数据查询概念(了解即可)

语句格式

  1. SELECT [ALL|DISTINCT]<目标列表达式>[,<目标列表达式>]..
  2. FROM<表名或视图名[,<表名或视图名>]...
  3. [WHERE<条件表达式>]
  4. [GROUP BY<列名1>[HAVING<条件表达式>]]
  5. [ORDER BY<列名2>[ASCIDESC]];

SQL基本结构包括3个子句

  • SELECT子句
    • 对应投影运算,指定查询结果中所需要的属性或表达式-
  • FROM子句
    • 对应笛卡尔积,给出查询所涉及的表,表可以是基本表、视图或查询表
  • WHERE子句
    • 对应选择运算,指定查询结果元组所需要满足的选择条件

      SELECT和FROM是必须的,其他是可选的

基本语法

  1. SELECT A1A2,....,An
  2. FROM R1R2,...,Rm
  3. WHERE P
  • A1,A2,…,A,代表需要查找的属性或表达式
  • R,R2,…,Rm代表查询所涉及的表
  • P代表谓词(即选择条件),如果省略WHERE子句,表示P为真

    SQL的查询结果中允许包含重复元组

SQL执行过程:

  • 首先对R,R2,…,Rm执行笛卡尔积
  • 然后在笛卡尔积中选择使得谓词P为真的记录
  • 再在A1,A,…A,属性列中进行投影运算,不消除重复元组
  • 如需消除重复元组,必须使用关键字DISTINCT

3.3 数据定义

3.3.1 创建基本表

(1)基本格式

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

(2)完整性约束条件

  • 列值非空(NOT NULL)
  • 列值唯一(UNIQUE)
  • 查列值是否满足一个布尔表达式(CHECK)

    (3)数据类型

    | 数据类型 | 含义 | | —- | —- | | CHAR(n) | 长度为n的定长字符串 | | VARCHAR(n) | 最大长度为n的变长字符串 | | INT | 长整数(也可以写作INTEGER) | | SMALLINT | 短整数 | | NUMERIC(p,d) | 定点数,由p位数字(不包括符号、小数点)组成,小数后面有d位数字 | | REAL | 取决于机器精度的浮点数 | | Double Precision | 取决于机器精度的双精度浮点数 | | FLOAT(n) | 浮点数,精度至少为n位数字 | | DATE | 日期,包含年、月、日,格式为YYYY-MM-DD | | TIME | 时间,包含一日的时、分、秒,格式为HH:MM:SS |

其中黄色标记的是常用的。

举个例子:

  1. CREATE TABLE Student
  2. (Sno CHAR(9) PRIMARY KEY, /* 列级完整性约束条件*/
  3. Sname CHAR(20) UNIQUE, /* Sname取唯一值*/
  4. Ssex CHAR(2) CHECK (Ssex IN (‘男’,‘女’),
  5. Sage SMALLINT NOT NULL,
  6. Sdept CHAR(20)
  7. );

PRIMARY KEY表示该属性作为主键

3.3.2 修改基本表

  1. ALTER TABLE <表名>
  2. [ ADD <新列名> <数据类型> [ 完整性约束 ] ]
  3. [ DROP <完整性约束名> ]
  4. [ ALTER COLUMN<列名> <数据类型> ];

3.3.3 删除基本表

  1. DROP TABLE <表名>[RESTRICT| CASCADE
  • RESTRICT:
    • 删除表是有限制的。欲删除的基本表不能被其他表的约束所引用
    • 如果存在依赖该表的对象,则此表不能被删除
  • CASCADE:删除该表没有限制。
  • 在删除基本表的同时,相关的依赖对象一起删除

3.4数据查询

3.4.1单表查询

(1)选择表中的若干列

[例1]查询全体学生的学号与姓名。

  1. SELECT SnoSname
  2. FROM Student;

该查询的执行过程是:

  1. 从Student表中依次取出每个元组
  2. 对每个元组仅选取Sno、Sname两个属性的值,形成一个新元组
  3. 最后将这些新元组组织为一个结果关系输出

[例2]查询全体学生所有信息。

  1. SELECT *
  2. FROM Student;

这里的*****符号表示查询所有内容。

给属性取列别名:
[例3]查询所有学生的所属系、学号和姓名,要求用中文显示列名

  1. SELECT Sdept 所属系,Sno 学号,Sname 姓名
  2. FROM Student

也可以使用AS关键词取别名

  1. SELECT Sdept AS 所属系,Sno AS 学号,Sname AS 姓名
  2. FROM Student

查询经过计算的值:
[例4]查全体学生的姓名及其出生年份。

  1. SELECT Sname2020-Sage /*假定当年的年份为2020年*/
  2. FROM Student;

输出结果:

Sname 2020-Sage
李勇 2000
刘晨 2001
王敏 2002
张立 2001

[例5]查询全体学生的姓名、出生年份和所有系,要求用小写字母表示所有系名:

  1. SELECT Sname NAME, 'Year of Birth:'BIRTH,year(GETDATE())-Sage BIRTHDAY,LOWER(Sdept) DEPARTMENT
  2. FROM Student;
  • 函数lower()将大写字母改为小写字母函数
  • getdate()获取当前系统的日期·函数
  • year()提取日期中的年份
  • 'Year of Birth:'BIRTH表示BIRTH这一列的值全是Year of Birth:

    (2)选择表中的若干组元素

    取消重复的行
    1. SELECTALL Sno
    2. FROM SC;
    执行上面的SELECT语句后,结果为:
Sno
200215121
200215121
200215121
200215122
200215122

指定DISTINCT关键词,去掉表中重复的行

  1. SELECT DISTINCT Sno
  2. FROM SC;

结果为:

Sno
200215121
200215122

选择运算

就是运用WHERE句子对数据进行筛选,常用的筛选语句有如下几个。

  • 比较运算:>、>=、<、<=、=、<>(或!=)
  • 范围查询:BETWEEN…AND
  • 集合查询:IN
  • 空值查询:IS NULL
  • 字符匹配查询:LIKE
  • 逻辑查询:AND、OR、NOT

下面举几个例子:
[例6]查询计算机科学系(CS)全体学生的名单。

  1. SELECT Sname
  2. FROM Student
  3. WHERE Sdept='CS';

[例7]查询所有出生日期在2002年以前的学生姓名及其年龄。

  1. SELECT SnameSage
  2. FROM Student
  3. WHERE year(GETDATE())-Sage <2002;

选择查询的方法主要有两种:

  1. 全表扫描法
  2. 索引搜索法

    一般来讲索引搜索法效率更高,因为全表扫描法需要遍历全表。

[例8]查询年龄在20~23岁(包括20岁和23岁)之间的学生的姓名、系别和年龄

  1. SELECT SnameSdeptSage
  2. FROM Student
  3. WHERE Sage BETWEEN 20 AND 23;

不在范围内就使用 NOT BETWEEN ... AND ...

[例9]查询信息系(IS)、数学系(MA)和计算机科学系(CS)学生的姓名和性别。

  1. SELECT SnameSsex
  2. FROM Student
  3. WHERE Sdept IN ( 'IS''MA''CS');

IN表示查询属性值在集合内的元组。 IN全表扫描 如果想要查询不存在集合内的则使用NOT IN

字符串匹配
  • **%**表示任意长度的字符串
    • ab%,表示所有以ab开头的任意长度的字符串;(例如abcd)
    • zhang%ab,表示以zhang开头,以ab结束,中间可以是任意个字符的字符串。(例如zhang123ab)
  • **符号_(下划线)**表示任意一个字符
    • ab_,表示所有以ab开头的3个字符的字符串,其中第3个字符为任意字符;(例如abc)
    • a__b表示所有以a开头,以b结束的4个字符的字符串,且第2、3个字符为任意字符。(例如:acbb)

[例10]查询所有姓刘学生的姓名、学号和性别。

  1. SELECT SnameSnoSsex
  2. FROM Student
  3. WHERE Sname LIKE‘刘%';

使用转义字符
[例11]查询DB_Design课程的课程号和学分。

  1. SELECT CnoCcredit
  2. FROM Course
  3. WHERE Cname LIKE 'DB\_Design' ESCAPE '\';

ESCAPE'\'表示“\”为换码字符。

涉及空值的查询

谓词:IS NULL或IS NOT NULL“IS”不能用“=”代替
[例12]某些学生选修课程后没有参加考试,所以有选课记录,但没有考试成绩。查询缺少成绩的学生的学号和相应的课程号。

  1. SELECT SnoCno
  2. FROM SC
  3. WHERE Grade IS NULL

多重条件的查询

逻辑运算符:AND和 OR来联结多个查询条件

  • AND的优先级高于OR
  • 可以用括号改变优先级

[例13]查询计算机系年龄在20岁以下的学生姓名。

  1. SELECT Sname
  2. FROM Student
  3. WHERE Sdept= 'CS' AND Sage<20

(3)ORDER BY子句

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

[例14]查询选修了3号课程的学生的学号及其成绩,查询结果按分数降序排列。

  1. SELECT SnoGrade
  2. FROM SC
  3. WHERE Cno= ' 3 '
  4. ORDER BY Grade DESC;

(4)聚集函数

  • 计数
    • COUNT ([DISTINCT|ALL]*)
    • COUNT ([DISTINCT|ALL]<列名>)
  • 计算总和
    • SUM([DISTINCT|ALL]<列名>)
  • 计算平均值
    • AVG ([DISTINCTALL]<列名>)
  • 最大最小值
    • MAX ([DISTINCT|ALL]<列名>)
    • MIN ([DISTINCTALL]<列名>)

[例15]查询学生总人数。

  1. SELECT COUNT(*)
  2. FROM Student;

[例16]查询选修了课程的学生人数。

  1. SELECT COUNT(DISTINCT Sno)
  2. FROM SC;

[例17]计算1号课程的学生平均成绩。

  1. SELECT AVG(Grade)
  2. FROM SC
  3. WHERE Cno= '1 ';

(5)GROUP BY 子句

该子句的作用是细化聚集函数的作用对象

  • 未对查询结果分组,聚集函数将作用于整个查询结果
  • 对查询结果分组后,聚集函数将分别作用于每个组作用对象
  • 是查询的中间结果表
  • 按指定的一列或多列值分组,值相等的为一组

举个例子:CS表

学号(Sno) 课程号(Cno) 成绩(Grade)
200215121 1 92
200215121 2 85
200215121 3 88
200215122 2 90
200215122 3 80

对该表使用GROUP BY Sno子句,则会划分出如下分组。

学号(Sno) 课程号(Cno) 成绩(Grade)
200215121 1 92
200215121 2 85
200215121 3 88
学号(Sno) 课程号(Cno) 成绩(Grade)
200215122 2 90
200215122 3 80

分组之后聚集函数作用的对象就是分组之后的相关属性

[例18]求各个课程号及相应的选课人数。

  1. SELECT Cno, COUNT(Sno) 选课人数
  2. FROM SC
  3. GROUP BY Cno ;

(6)HAVING语句

HAVING短语与WHERE子句的区别:作用对象不同

  • WHERE子句作用于基表或视图,从中选择满足条件的元组。
  • HAVING短语作用于,从中选择满足条件的组。

    简单的来讲,WHERE子句用于属性的条件查询,HAVING子句用于聚集函数的条件查询

[例19]查询有3门以上课程是90分以上的学生的学号及(90分以上的)课程数。

  1. SELECT Sno,COUNT(*)
  2. FROM SC
  3. WHERE Grade>=90
  4. GROUP BY Sno
  5. HAVING COUNT(*)>=3;

注意:HAVING子句必须跟着GROUP子句之后

接着来一个例题复习一下前面的内容
查询各个专业的选修课程总学时大于10个学时的专业号和选修课程总学时,并按降序排序

  1. select dbo.课程.专业,sum(dbo.课程.学时)
  2. from dbo.课程
  3. where dbo.课程.课程类别='选修课程'
  4. group by dbo.课程.专业
  5. having sum(dbo.课程.学时)>10
  6. order by sum(dbo.课程.学时) desc

几个注意点: 1.大小写不区分。 2.dbo是表名的前缀,可以忽略不写。 3.课程.XX表示课程表里面的XX元组。


3.4.2 连接查询

(1)基本定义

连接条件或连接谓词:用来连接两个表的条件一般格式:

  1. [<表名1>.]<列名1> <比较运算符> [K<表名2>.]<列名2>
  2. [<表名1>.]<列名1> BETWEEN [<表名2>.]<列名2> AND [<表名2>.]<列名3>
  • 连接字段:连接谓词中的列名称
  • 连接条件中的各连接字段类型必须是可比的,但名字不必是相同的

    一般情况下都是等值连接,所以比较运算符一般为=

[例20]查询每个学生及其选修课程的情况

  1. SELECT Student.*,SC.*
  2. FROM Student,SC
  3. WHERE Student.Sno = SC.Sno;

(2)自身连接

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

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

[例21]查询每一门课的间接先修课(即先修课的先修课)

  1. SELECT FIRST.Cno, SECOND.Cpno
  2. FROM Course FlRST,Course SECOND
  3. WHERE FIRST.Cpno = SECOND.Cno;

(3)外连接

外连接与普通连接的区别

  • 普通连接操作只输出满足连接条件的元组
  • 外连接操作以指定表为连接主体,将主体表中不满足连接条件的元组一并输出
  • 左外连接 (LEFT OUT JOIN)
    • 列出左边关系(如本例Student)中所有的元组
  • 右外连接(RIGHT OUT JOIN)
    • 列出右边关系中所有的元组

举个例子:
[例22]查询每个(所有)学生及其选修课程的情况

  1. SELECT Student.SnoSnameSsexSageSdeptCnoGrade
  2. FROM Student LEFT OUT JOIN SC ON(Student.Sno=SC.Sno); //左外连接

查询之后的表如下:

Sno Sname Ssex Sage Sdept Cno Grade
200215121 李勇 20 CS 1 92
200215121 李勇 20 CS 2 85
200215121 李勇 20 CS 3 88
200215122 刘晨 19 CS 2 90
200215122 刘晨 19 CS 3 80
200215123 王敏 18 MA NULL NULL
200215125 张立 19 IS NULL NULL

(4)符合条件连接

也就是WHERE子句中含多个连接条件

[例23]查询选修2号课程且成绩在90分以上的所有学生

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

3.4.3 嵌套查询

(1)嵌套查询概述

  • 一个SELECT-FROM-WHERE语句称为一个查询块
  • 将一个查询块嵌套在另一个查询块的WHERE子句或HAVING短语的条件中的查询称为嵌套查询

举个例子:

  1. SELECT Sname
  2. /*外层查询/父查询*/
  3. FROM Student
  4. WHERE Sno IN
  5. (SELECT Sno
  6. FROM Sc
  7. WHERE Cno= '2 ') ;/*内层查询/子查询*

一些性质
  • 子查询的限制
    • 不能使用ORDER BY子句
  • 层层嵌套方式反映了SQL语言的结构化
  • 有些嵌套查询可以用连接运算替代

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

(2)带有IN谓词的子查询

[例24]查询与“刘晨”在同一个系学习的学生。
这里的步骤就是:
1.首先选择出刘晨所在的系
2.再去从这个系里面选择学生。

  1. SELECT SnoSnameSdept
  2. FROM Student
  3. WHERE Sdept IN
  4. (SELECT Sdept
  5. FROM Student
  6. WHERE Sname=‘刘晨’);

使用自身连接也可以完成该题。代码如下:

  1. SELECT S1.SnoS1.SnameS1.Sdept
  2. FROM Student S1Student s2
  3. WHERE S1.Sdept = S2.Sdept AND S2.Sname = '刘晨';

该题是不相关子查询,因为子查询的WHERE条件不依赖于父查询的WHERE条件。

(3)带有比较运算符的子查询

[例25]找出每个学生超过他选修课程平均成绩的课程号。

  1. SELECT SnoCno
  2. FROM SC x
  3. WHERE Grade >=(SELECT AVG(Grade)
  4. FROM SC y
  5. WHERE y.Sno=x.Sno);

该题是相关子查询。因为子查询的条件中,依赖于父查询的条件。

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

谓词语义:

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

简单来讲,出现某一就用谓词ANY,出现所有就用ALL

配合使用其他比较运算符

  1. >ANY 大于子查询结果中的某个值
  2. > ALL 大于子查询结果中的所有值
  3. <ANY 小于子查询结果中的某个值
  4. <ALL 小于子查询结果中的所有值
  5. >=ANY 大于等于子查询结果中的某个值
  6. >= ALL 大于等于子查询结果中的所有值
  7. <= ANY 小于等于子查询结果中的某个值
  8. <= ALL 小于等于子查询结果中的所有值
  9. =ANY 等于子查询结果中的某个值
  10. =ALL 等于子查询结果中的所有值(通常没有实际意义)
  11. !=(或<>)ANY 不等于子查询结果中的某个值
  12. !=(或<>)ALL 不等于子查询结果中的任何一个值

[例26]查询其他系中比计算机科学某一学生年龄小的学生姓名和年龄

  1. SELECT SnameSage
  2. FROM Student
  3. WHERE Sage <ANY(
  4. SELECT Sage
  5. FROM Student
  6. WHERE Sdept= 'CS'
  7. )AND Sdept != 'CS'

[例27]求年龄大于所有信息系女同学年龄的男学生姓名和年龄

  1. SELECT Sname, Sage
  2. FROM Student
  3. WHERE Ssex='男'
  4. AND Sage > ALL (SELECT Sage
  5. FROM Student
  6. WHERE Ssex='女' and Sdept='lS');

(5)带有EXISTS谓词的子查询

带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值**true**或逻辑假值**false**

若内层查询结果非空,则外层的WHERE子句返回真值 若内层查询结果为空,则外层的WHERE子句返回假值

NOT EXISTS谓词

若内层查询结果非空,则外层的WHERE子句返回假值 若内层查询结果为空,则外层的WHERE子句返回真值

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

  1. 用嵌套查询
  2. SELECT Sname
  3. FROM Student
  4. WHERE EXISTS
  5. (SELECT *
  6. FROM SC
  7. WHERE SC.Sno=Student.Sno AND Cno= '1 ');

一般情况下exits引导的子查询都是相关子查询

[例28]查询与“刘晨”在同一个系学习的学生。可以用带EXISTS谓词的子查询替换:

  1. SELECT SnoSnameSdept
  2. FROM Student S1
  3. WHERE EXISTS
  4. (SELEC T*
  5. FROM Student S2
  6. WHERE S2.Sdept = S1.Sdept AND
  7. S2.Sname =‘刘晨’);

[例29]查询选修了全部课程的学生姓名。
可将题目的意思转换成等价的形式:查询这样的学生,没有一门课程是他不选修的

  1. SELECT Sname
  2. FROM Student
  3. WHERE NOT EXISTS
  4. (SELECT*
  5. FROM Course
  6. WHERE NOT EXISTS //--判断学生Student.Sno没有选修课程Course.Cno
  7. (SELECT*
  8. FROM sc
  9. WHERE Sno= Student.Sno
  10. AND Cno= Course.Cno)
  11. ) ;

3.4.4 集合查询

集合操作的种类

  • 并操作 UNION
  • 交操作 INTERSECT
  • 差操作 EXCEPT

    (1)并操作

    [例30]查询计算机科学系的学生及年龄不大于19岁的学生。
    方法一:
    1. SELECT*
    2. FROM Student
    3. WHERE Sdept= 'SCS'
    4. UNION
    5. SELECT*
    6. FROM Student
    7. WHERE Sage<=19;

    UNION:将多个查询结果合并起来时,系统自动去掉重复元组。 UNION ALL:将多个查询结果合并起来时,保留重复元组

方法二:

  1. SELECT DISTINCT*
  2. FROM Student
  3. WHERE Sdept= 'CS'OR Sage<=19;

(2)交集操作

[例31]查询计算机科学系的学生与年龄不大于19岁的学生的交集

  1. SELECT*
  2. FROM Student
  3. WHERE Sdept='Cs'
  4. INTERSECT
  5. SELECT*
  6. FROM Student
  7. WHERE Sage<=19

(3)差集操作

[例32]查询计算机科学系的学生与年龄不大于19岁的学生的差集。

  1. SELECT *
  2. FROM Student
  3. WHERE Sdept='CS'
  4. EXCEPT
  5. SELECT *
  6. FROM Student
  7. WHERE Sage <=19;

3.5 数据更新

3.5.1 数据的增加

数据的插入

语句格式

  1. INSERT
  2. INTO <表名>[(<属性列1>[,<属性列2>...)]
  3. VALUES(<常量1>[,<常量2>]
  4. )
  • INTO子句

    属性列的顺序可与表定义中的顺序不一致 没有指定属性列 指定部分属性列

  • VALUES子句

    提供的值必须与INTO子句匹配 值的个数 值的类型

举个例子:
[例33]将一个新学生元组(学号:200215128;姓名:陈冬;性别:男;所在系:IS;年龄:18岁)插入到Student表中。

  1. INSERT
  2. INTO
  3. Student (SnoSnameSsexSdeptSage)
  4. VALUES ('200215128''陈冬''男''IS'18);

没有明确赋值的属性会被自动赋予NULL值

插入子查询结果

语句格式

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

[例34]对每一个系,求学生的平均年龄,并把结果存入数据库。
第一步:建表

  1. CREATE TABLE Dept_age
  2. (Sdept CHAR(15)/*系名*l
  3. Avg_age SMALLINT);/*学生平均年龄*/

第二步:插入数据

  1. INSERT
  2. INTO
  3. Dept_age(SdeptAvg_age)
  4. SELECT SdeptAVG(Sage)
  5. FROM Student
  6. GROUP BY Sdept;

3.5.2 数据的删除

语句格式:

  1. DELETE
  2. FROM <表名>
  3. [WHERE<条件>];

例子:
[例35]删除学号为200215128的学生记录。

  1. DELETE
  2. FROM Student
  3. WHERE Sno= 200215128 ';

注意:delete的删除只是删除数据,不删除表本身。 删除整个表用drop

[例36]删除男同学所有学分为3的课程的选课记录

  1. DELETE
  2. FROM SC
  3. WHERE ‘男’=
  4. (SELETE Ssex
  5. FROM Student
  6. WHERE Student.Sno=SC.Sno)
  7. and 3=(SELETE Ccredit
  8. FROM Course
  9. WHERE Course.Cno = SC.Cno) ;

不能直接查询Ssex='男',因为Ssex不是SC表中的属性。

3.5.3 数据的更新

语句格式

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

例子:
[例37]将学生200215121的年龄改为22岁

  1. UPDATE Student
  2. SET Sage=22
  3. WHERE Sno='200215121 ';

[例38]将所有学生的年龄增加1岁

  1. UPDATE Student
  2. SET Sage= Sage+1;

3.6 视图

(1)语句格式

  1. CREATE VIEW
  2. <视图名>[(<列名>[,<列名>]...)]
  3. AS <Select查询语句>;

例如:
[例38]:建立信息系学生的视图。

  1. CREATE VIEW IS_Student
  2. AS
  3. SELECT Sno,SnameSage
  4. FROM Student
  5. WHERE Sdept='IS';
  1. SELECT SnoSage
  2. FROM IS_Student
  3. WHERE Sage<20;

撤销视图:
DROP VIEW<视图名>;例如:

  1. DROPVIEW IS_Student;

视图可以理解为一个表,与基本表具有一样的性质,也可以像基本表一样使用。 大部分用于简化复杂的用户查询的操作。

(2)视图的特点

  • 虚表,是从一个或几个基本表(或视图)导出的表
    • 视图将导致性能开销,因为视图是动态生成的
    • 基于视图的查询是受限的
    • 视图的更新是受限的
  • 只存放视图的定义,不存放视图对应的数据
  • 基表中的数据发生变化,从视图中查询出的数据也随之改变
  • 一定程度上保证了数据的逻辑独立性

    (3)视图更新

    格式:
    1. UPDATE SC
    2. SET AVG(Grade)=90
    3. WHERE Sno=‘200215121'

    UPDATE后面是需要更新的表 SET后面是需要更新的属性

(4)视图更新的限制

举个例子:

  1. //S_G视图的子查询定义:
  2. CREATE VIEW S_G (SnoGavg)
  3. AS
  4. SELECT SnoAVG(Grade)
  5. FROM SC
  6. GROUP BY Sno
  7. //将学号200215121的Gavg值更新为90
  8. UPDATE S_G
  9. SET Gavg=90
  10. WHERE Sno=‘200215121’;

该视图只更新了平均成绩但是没有更新基本表表的各个学生的成绩。

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

(5)视图的创建

语句格式

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

组成视图的属性列名:全部省略或全部指定子查询不允许含有ORDER BY子句和DISTINCT短语

WITH CHECK OPTION 表示视图更新受限,一般情况都加上去。


3.7 触发器(了解即可)

(1)定义触发器

CREATE TRIGGER语法格式:

  1. CREATE TRIGGER<触发器名> //定义触发器的名字
  2. {BEFORE |AFTER}<触发事件>ON<表名> //before和after表示激活触发器的时间是在执行前还是后
  3. REFERENCING NEW|OLD ROW AS<变量> //指出引用的变量
  4. FOR EACH {Row | STATEMENT} //触发器的类型
  5. [WHEN<触发条件>] //触发的条件
  6. <触发动作体>

触发事件:INSERT、DELETE、UPDATE。 触发器类型

  • 行级触发器(FOR EACH ROW)
  • 语句级触发器(FOR EACH STATEMENT)

例如,假设在TEACHER表上创建了一个AFTER UPDATE触发器。如果表TEACHER有1000行,执行如下语句:

  1. UPDATE TEACHER SET Deptno=5;
  • 如果该触发器为语句级触发器,那么执行完该语句后,触发动作只发生一次
  • 如果是行级触发器,触发动作将执行1000次

    触发动作体 触发动作体可以是一个匿名PL/SQL过程块 也可以是对已创建存储过程的调用

[例39]定义一个AFTER触发器,为工资表定义完整性规则“教师的基本工资不得低于1000元,如果低于1000元,自动改为1000元”。

  1. CREATE TRIGGER updateCheck
  2. AFTER UPDATE //这里定义update是触发器事件
  3. ON 工资
  4. WHEN new.基本工资<1000 //new指的就是新插入的数据
  5. BEGIN //这里是触发动作体,修改工资低于1000的老师的工资
  6. UPDATE 工资
  7. SET 基本工资=1000
  8. WHERE 工资.职工号=new.职工号;
  9. END;

(2)激活触发器

由触发事件自动激活。

一个数据表上可能定义了多个触发器
同一个表上的多个触发器激活时遵循如下的执行顺序:
(1)执行该表上的BEFORE触发器;
(2)激活触发器的SQL语句;
(3)执行该表上的AFTER触发器。

(3)删除触发器

删除触发器的SQL语法:

  1. DROP TRIGGER<触发器名> ON <表名>;