SQL:结构化查询语言,是关系数据库的标准语言
目前没有一个数据库系统可以支持SQL标准的所有概念和特性
SQL 的特点
综合统一
高度非过程化
面向集合的操作方式
以同一种语言结构提供多种使用方式
语言简洁、易学易用
SQL功能极强,完成核心功能只用到9个动词
SQL功能 | 动词 |
---|---|
数据查询 | SELECT |
数据定义 | CREATE, DROP, ALTER |
数据操纵 | INSERT, UPDATE, DELETE |
数据控制 | GRANT, REVOKE |
SQL 支持关系数据库三级模式结构
实例数据库
Student(Sno,Sname,Ssex,Sage,Sdept)
Course(Cno,Cname,Cpno,Ccredit)
SC(Sno,Cno,Grade)
SQL 的数据定义功能:定义各种数据库对象
一个数据库里可以建立多个模式
一个模式下通常包括多个表、视图和索引等数据库对象
数据字典
eg.3.1 为用户WANG定义一个学生-课程模式S-T
CREATE SCHEMA "S-T" AUTHORIZATION WANG;
eg.3.2 该语句没有定义模式名,模式名隐含为用户名
CREATE SCHEMA AUTHORIZATION WANG;
定义模式实际上定义了一个命名空间(或者说目录)
在这个空间上可以定义该模式包含的数据库对象,例如基本表,索引,视图等
在CREATE SCHEMA 中可以接受 CREATE TABLE(基本表),CREATE VIEW(视图),GRANT(索引) 子句
CREATE SCHEMA <模式名> AUTHORIZATION <用户名> [<表定义子句>|<视图定义子句>|<授权定义子句>]
eg.3.3 为用户WANG 创建了一个模式TEST ,并在其中定义一个表 TAB1
CREATE SCHEMA TEST AUTHORIZATION WANG
CREATE TABLE TAB1 (COL1 SMALLINT,
COL2 INT,
COL3 CHAR(20),
COL4 NUMERIC(10,3),
COL5 DECIMAL(5,2)
);
语法
DROP SCHEMA <模式名>
eg.3.4 删除模式ZHANG 同时该模式中定义的表TAB1也被删除
DROP SCHEMA ZHANG CASCADE;
CREATE TABLE <表名> /*基本表的名称*/
(<列名><数据类型>)[<列级完整性约束条件>] /*组成该表的列*/
[,<列名><数据类型>][<列级完整性约束条件>]]
...
[,<表级完整性约束条件>]);
【eg.3.5】 建立“学生”表 Student.学号时主码,姓名值取唯一。
CREATE TABLE Student
(
Sno CHAR(9) PAIMARY KEY, /*列级完整性约束条件,Sno为主码*/
Sname CHAR(20) UNIQUE, /*Sname取唯一值*/
Ssex CHAR(2),
Sage SMALLINT,
Sdept CHAR(20)
);
【eg.3.6】建立一个”课程“表 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*/
);
【eg.3.7】建立一个学生选课表 SC
CREATE TABLE sc
(
Sno CHAR(9),
Cno CHAR(4),
Grade SMALLINT,
PRIMARY KEY(Sno,Cno),/*主码由两个属性构成,必须作为表级完整性进行定义*/
FOREIGN KEY(Sno) REFERENCES Student(Sno),
/*表级完整性约束条件,Sno是外码,被参照表是Student*/
FOREIGN KEY(Cno) REFERENCES Course(Cno)
/*表级完整性约束条件,Cno是外码,被参照表是Course*/
);
数据类型
模式与表
每一个基本表需属于某个模式
定义基本表所属模式的方式:
方法一:在表名中明显给出模式名
CREATE TABLE "S-T".Student(...); /* 模式名为S-T*/
CREATE TABLE "S-T".Course(...);
CREATE TABLE "S-T".SC(...);
方法二:在创建模式的同时创建表
方法三:设置所属的模式
ALTER TABLE<表名>
[ADD[COLUMN]]<新列名><数据类型>[完整性约束]]
[ADD <表级完整性约束>]
[DROP[COLUMN]<列名>[CASCADE|RESTRICT]]
[DROP CONSTRAINT<完整性约束名>[RESTRICT|CASCADE]]
[ALTER COLUMN<列名><数据类型>];
表名是要修改的基本表
ADD子句用于添加新列、新的列级完整性约束条件和新的表级完整性约束条件
DROP COLUMN 子句用于删除表中的列
DROP CONSTRAINT子句用于删除指定的完整性约束条件
ALTER COLUMN 子句用于修改原有的列定义包括修改列名和数控类型
【eg. 3.8】向Student表中增加“入学时间”列,其数据类型为日期型
ALTER TABLE Student ADD S_entrance DATE;
不管基本表中有无数据,新增加的列一列为空值
【eg. 3.9】将年龄的数据类型由字符型(假设原来的数据类型是字符型)改为整数;
ALTER TABLE Student ALTER COLUMN Sage INT;
【eg. 3.10】添加课程名称必须取唯一值的约束条件
ALTER TABLE Course ADD UNIQUE(Cname);
DROP TABLE<表名>[RESTRICT|CASCADE];
【eg. 3.11】删除Student表
DROP TABLE Student CASCADE;
语句格式
CREATE[UNIQUE][CLUSTER] INDEX<索引名> ON<表名>(<列名>[<次序>],
[,<列名>[<次序>]]...);
【eg. 3.13】为学生-课程数据库中Student,Course,SC三个表建立索引。
Student表按照学号升序建唯一索引,
Course表按课程号升序建立唯一索引,
SC表按照学号升序和课程号降序建唯一索引。
CRATE UNIQUE INDEX Stusno ON Student(Sno);
CRATE UNIQUE INDEX Coucno ON Course(Cno);
CRATE UNIQUE INDEX SCno ON SC(Sno ASC,Cno DESC);
语法格式
ALTER INDEX<旧索引> RENAME TO <新索引>;
【eg. 3.14】将SC表中的SCno索引名改为SCSno
ALTER INDEX SCno RENAME TO SCSno;
语法格式
DROP INDEX <索引名>;
删除索引时,系统会从数据字典里删去有关该索引的描述
【eg. 3.15】删除Student 表中的Stusname索引
DROP INDEX Stusname;
数据查询
语法格式
SELECT[ALL|DISTINCT]<目标列表达式>[,<目标列>]...
FROM<表名或者视图名>[,<表名或者视图名>]...|(SELECT 语句)
[AS]<别名>
[WHERE<条件表达式>]
[GROUP BY <列名1>][HAVING<条件表达式>]]
[ORDER BY <列名2>[ASC|DESC]];
子句 | 作用 |
---|---|
SELECT子句 | 指定要现实的属性列 |
FROM子句 | 指定查询对象 |
WHERE子句 | 指定查询条件 |
GROUP BY 子句 | 对查询结果按指定列的值分组,该属性列值相等的元组为一组。通常会在每组中作用聚集函数。 |
HAVING 子句 | 只有满足指定田条件的组才予以输出 |
ORDER BY 子句 | 对查询结果表按指定列值的升序或降序排列 |
【eg. 3.16】查询全体学生的学号和姓名
SELECT Sno,Sname
FROM Student;
【eg. 3.17】查询全体学生的详细记录
SELECT Sno,Sname,Ssex,Sage,Sdept
FROM Student;
或
SELECT *
FROM Student;
【eg. 3.18】查询全体学生的姓名及其出生年份
SELECT Sname,2020-Sage
FROM Student;
【eg. 3.19】查询全体学生的姓名,出生年份和所在的院系,要求小写字母表示系名
SELECT Sname,'Year of Birth:',2020-Sage,LOWER(Sdept)
FORM Student;
【eg. 3.21】使用列别名改变查询结果的列标题
SELECT Sname NAME,
'Year of Birth:' BIRTH,2020-Sage BIRTHDAY,LOWER(Sdept) DEPARTMANT
FROM Student;
如果没有指定DISTINCT关键词,则缺省值为ALL(不去重)
【eg. 3.21】查询选修了课程的学生学号
SELECT Sno
FROM SC;
SELECT DISTINCT Sno
FROM SC;
【eg. 3.22】查询计算机科学系全体学生的名单
SELECT Sname
FROM Student
WHERE Sdept='CS';
【eg. 3.23】查询所有年龄在20岁以下的学生姓名及年龄
SELECT Sname,Sage
FROM Student
WHERE Sage<20;
【eg. 3.24】查询考试有不及格的学生的学号
SELECT DISTINCT Sno
FROM Student
WHERE Grade<60;
确定范围
谓词:BETWEEN… AND…
NOT BETWEEN… AND…
【eg. 3.25】查询年龄在20—23岁(包括20和23)之间的学生姓名、系别、年龄
SELECT Sname,Sdept,Sage
FROM Student
WHERE Sage BETWEEN 20 AND 23;
/*年龄不在20—23岁(包括20和23)之间的学生姓名、系别、年龄*/
SELECT Sname,Sdept,Sage
FROM Student
WHERE Sage NOT BETWEEN 20 AND 23;
确定集合
谓词:IN<值表>,
NOT IN<值表>
【eg. 3.27】查询计算机系(CS)、数学系(MA)和信息系(IS) 学生姓名和性别
SELECT Sname,Sage
FROM Student
WHERE Sdept IN ('CS','MA','IS');
/*查询不是计算机系(CS)、数学系(MA)和信息系(IS) 学生姓名和性别*/
SELECT Sname,Sage
FROM Student
WHERE Sdept NOT IN ('CS','MA','IS');
字符匹配
谓词:[NOT] LIKE ‘<匹配串>’ [ESCAPE’<换码字符>’]
匹配串可以是一个完整的字符串,也可以含有通配符%和_
%(百分号) 代表任意长度(长度也可以为0)的字符串
例如a%b 表示以a 开头,以b 结尾的任意长度的字符串
_(下横线) 代表任意单个字符
例如a_b 表示以a 开头,以b 结尾的长度为3 的任意字符串
【eg. 3.29】查询学号为2018304188 的学生的详细情况
SELECT *
FROM Student
WHERE Sno LIKE '2018314188';
等价于
SELECT *
FROM Student
WHERE Sno='2018314188';
【eg. 3.30】查询所有姓刘学生的姓名、学号和性别;
SELECT Sname,Sno,Ssex
FROM Student
WHERE Sname LIKE '刘%';
【eg. 3.31】查询姓“欧阳”且全名为三个汉字的学生的姓名;
SELECT Sname
FROM Student
WHERE Sname LIKE '欧阳__'; /*一个汉字两个字符长度*/
【eg. 3.32】查询名字中第二个字为“阳”字的学生的姓名和学号;
SELECT Sname,Sno
FROM Student
WHERE Sname LIKE '__阳%';
【eg. 3.33】查询所有不姓刘的学生姓名、学号和性别;
SELECT Sname,Sno,Ssex
FROM Student
WHERE Sname NOT LIKE '刘%';
【eg. 3.34】查询DB_Design 课程的课程号和学分;
SELECT Cno,Ccredit
FROM Course
WHERE Cname LIKE 'DB\_Design' ESCAPE'\'; /* ESCAPE'\' 表示\ 之后的字符为普通字符*/
【eg. 3.35】 查询以“DB_"开头,且倒数第三个字符为”i“ 的课程的详细情况
SELECT *
FROM Course
WHERE Cname LIKE 'DB\_%i__' ESCAPE'\'; /* ESCAPE'\' 表示"\"为转换字符 */
谓词:
IS NULL或IS NOT NULL
【eg. 3.36】 某些学生选修课程后没有参加考试,所以有选课记录但没有考试成绩。查询缺少成绩的学生的学号和相应的课程号
SELECT Sno,Cno
FROM SC
WHERE Gade IS NULL;
多重条件查询
逻辑运算符:AND 和OR 来连接多个查询条件
【eg. 3.38】 查询计算机系年龄在20岁以下的学生姓名
SELECT Sname
FROM Student
WHERE Sdept='CS' AND Sage<20;
【eg. 3.27】查询计算机系(CS)、数学系(MA)和信息系(IS) 学生姓名和性别
SELECT Sname,Sage
FROM Student
WHERE Sdept IN ('CS','MA','IS');
/*查询不是计算机系(CS)、数学系(MA)和信息系(IS) 学生姓名和性别*/
SELECT Sname,Sage
FROM Student
WHERE Sdept NOT IN ('CS','MA','IS');
也可以改写为
SELECT Sname,Sage
FROM Student
WHERE Sdept='CS' OR Sdept='MA' OR Sdept='IS';
【eg. 3.39】查询选修了三门课的学生的学号以及成绩,查询结果按照分数降序排列
SELECT Sno,Grade
FROM SC
WHERE Cno='3'
ORDER BY Grade DESC;
【eg. 3.40】查询全体学生情况,查询结果按照所在院系的系号排列,同一系的学生按照年龄降序排列
SELECT *
FROM Student
ORDER BY Sdept (ASC),Sage DESC;
聚集函数:
统计元组的个数
COUNT(*)
统计一列中值的个数
COUNT([DISTINCT|ALL]<列名>)
计算一列值的总和(此列必须为数值型)
SUM([DISTINCT|ALL<列名>])
计算一列值的平均值(此列必须为数值型)
AVG([DICTINCT|ALL<列名>])
求一列中最大值和最小值
MAX([DISTINCT|ALL<列名>])
MIN([DISTINCT|ALL<列名>])
【eg. 3.41】查询学生总人数
SELECT COUNT(*)
FROM Student;
【eg. 3.42】查询选修了课程的总人数
SELECT COUNT(DISTINCT Sno)
FROM SC;
【eg. 3.43】计算1号课程的学生平均成绩
SELECT AVG(Grade)
FROM SC
WHERE Cno='1';
【eg. 3.44】查询选修了1号课程的学生的最高分数
SELECT MAX(Grade)
FROM SC
WHERE Cno='1';
【eg. 3.45】查询学生2018304188选修课程的总学分数
SELECT SUM(Ccredit)
FROM SC,Course
WHERE Sno='2018304188' AND SC.Cno=Course.Cno;
GROUP BY 子句
细化聚集函数的作用对象
【eg. 3.46】求每个课程号及相应的选课人数
SELECT Cno,COUNT(Sno)
FROM SC
GROUP BY Cno; /* 以Cno为分组属性 */
【eg. 3.47】查询选修了三门以上的课程的学生学号
SELECT Sno
FROM SC
GROUP BY Sno
HAVING COUNT(*)>3;
【eg. 3.48】查询平均成绩大于等于90分的学生学号和平均成绩
SELECT Sno,AVG(Grade)
FROM SC
GROUP BY Sno
HAVING AVG(Grade)>=90;
WHERE 子句不能用聚集函数作为条件表达式。
【练习一】列出计算机系姓刘的同学的信息,按照学号大小排序
SELECT *
FROM Student
WHERE Sdept='CS' AND Sname LIKE '刘%'
ORDER BY Sno;
【练习二】按系区分男女统计各系学生的人数、并按照人数降序排列
SELECT Sdept,Ssex,COUNT(Sno)
FROM Student
GRUOP BY Sdept,Ssex
ORDER BY COUNT(Sno)DESC;
不像关系代数中”连接“是用一个特殊符号来表达的,在SQL中”连接“是用”连接条件“来表达的
连接条件或连接谓词:用来连接两个表的条件
一般格式
连接字段:连接谓词中的列名称
【eg. 3.49】查询每个学生及其选修课程的情况
SELECT Student.*,SC.*
FROM Student,SC
WHERE Student.Sno=SC.Sno;
【eg. 3.50】对上例用自然连接完成
SELECT Student.Sno,Sname,Ssex,Sage.Sdept,Cno,Grade/*Student.Sno表明只保留了Student中的Sno */
FROM Student,SC
WHERE Student.Sno=SC.Sno;
连接操作的执行过程
(1). 嵌套循环法(NESTED-LOOP)
(2).排序合并法(SORT-MERGE)
(3).索引连接法(INDEX-JOIN)
【eg. 3.51】查询选修了2号课程且成绩在90分以上的所有学生的学号和姓名
SELECT Student.Sno,Sname
FROM Student,SC
WHERE Student.Sno=SC.Sno AND SC.Cno='2' AND SC.Grade>90;
/* Student.Sno=SC.Sno 连接谓词“=” 选择谓词 AND*/
【eg. 3.52】查询每一门课的直接先修课的名称
SELECT FIRST.Cname,SECOND.Cname
FROM Course FIRST,Course SECOND
WHERE FIRST.Cpno=SECOND.Cno;
【eg. 3.53】改写【eg. 3.49】查询每个学生及其选修课程的情况
SELECT Student.*,SC.*
FROM Student,SC
WHERE Student.Sno=SC.Sno;
SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student LEFT OUT JOIN SC ON (Student.Sno=SC.Sno);
或
WHERE Student.Sno(+)=SC.Sno;
【eg. 3.53】查询每个学生的学号、姓名、选修的课程名以及成绩
SELECT Student.Sno,Sname,Cno,Grade
FROM Student,SC,Course /*多表连接*/
WHERE Student.Sno=SC.Sno
AND SC.Cno=Course.Cno;
嵌套查询概述
SELECT Sname /*外层查询/父查询*/
FROM Student
WHERE Sno IN
(SELECT Sno /*内层查询/子查询*/
FROM SC
WHERE Cno='2'
);
嵌套查询求解方法
【eg. 3.55】查询与“刘晨”在同一个系学习的学生,此查询要求可以分布完成
/*1.确定“刘晨”所在系名*/
SELECT Sdept
FROM Studnt
WHERE Sname='刘晨';
/*结果为:CS*/
/*2. 查找所有在CS系学习的学生*/
SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept='CS';
/*将第一步查询嵌入第二步查询的条件中*/
SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept IN
(SELECT Sdept
FROM Student
WHERE Sname='刘晨');
此查询为不相关子查询
用自身连接完成【eg. 3.55】查询要求
SELECT S1.Sno,S1.Sname,S1.Sdept
FROM Student S1,Student S2
WHERE S1.Sdept=S2.Sdept AND S2.Sname='刘晨';
【eg. 3.56】查询选修了课程名为“信息系统”的学生姓名和学号
SELECT Sno,Sname /*3. 最后再Student关系中取出Sno和Snmae*/
FROM Student
WHERE Sno IN
(SELECT Sno /*2. 然后再SC关系里找到选修了三号课程的学生学号*/
FROM SC
WHERE Cno IN
(SELECT Cno /*1. 首先在Course关系中找出“信息系统”的课程号,为三号*/
FROM Course
WHERE Cname='信息系统'
)
);
用连接查询来实现【eg. 3.56】
SELET Sno,Sname
FROM Student,SC,Course
WHERE Student.Sno=SC.Sno AND
SC.Cno=Course.Cno AND
Course.Cname='信息系统';
在【eg. 3.55】查询与“刘晨”在同一个系学习的学生,此查询要求可以分布完成
SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept = /*由于一个学生只能在一个系学习,用=代替*/
(SELECT Sdept
FROM Student
WHERE Sname='李晨'
);
【eg. 3.57】找出每个学生超过他选修课平均成绩的课程号
SELECT Cno
FROM SC x
WHERE Grade>=(SELECT AVG(Grade)
FROM SC y
WHERE y.Sno=x.Sno
);
此查询为相关子查询
可能执行的过程
SELECT AVG(Grade)
FROM SC y
WHERE y.Sno='2018304188';
SELECT Sno,Cno
FROM SC x
WHERE Grade>=(SELECT AVG(Grade)
FROM SC y
WHERE y.Sno='2018304188');
执行该查询,得到结果
使用ANY 或 ALL 谓词时必须同时使用比较运算
语义为:
>ANY | 大于子查询结果中的某个值 |
>ALL | 大于子查询中的所有值 |
小于子查询结果中的某个值 |
|
小于子查询结果中的所有值 |
|
>=ANY | 大于等于子查询结果中的某个值 |
>=ALL | 大于等于子查询结果中的所有值 |
【eg. 3.58】查询非计算机科学系中比计算机科学系 任意一个 学生连接小的学生姓名和年龄
SELECT Sname,Sage
FROM Student
WHERE Sage<ANY (SELECT Sage
FROM Student
WHERE Sdept='CS'
)
AND Sdept<>'CS'; /*父查询块中的条件 Sdept!='CS'*/
SELECT Sname
FROM Student
WHERE Sage<
(SELECT MAX(Sage)
FROM Student
WHERE Sdept='CS'
)
AND Sdept<>'CS';
【eg. 3.59】查询非计算机科学系中比计算机科学系 所有 学生年龄都小的学生姓名及年龄
方法一:用ALL谓词
SELECT Sname,Sage
FROM Student
WHERE Sage<ALL
(SELECT Sage
FROM Student
WHERE Sdept='CS')
AND Sdept<>'CS';
方法二:用聚集函数
SELECT Sname,Sage
FROM Student
WHERE Sage<
(SELECT MIN(Sage)
FROM Student
WHERE Sdept='CS'
)
AND Sdept<>'CS';
【eg. 3.60】查询所有选修了1号课程的学生姓名
思路分析:
SELECT Sname
FROM Student
WHERE EXISTS
(SELECT*
FROM SC
WHERE Sno=Student.Sno AND Cno='1'
);
【eg. 3.61】查询没有选修课程1号的学生姓名
SELECT Sname
FROM Student
WHERE NOT EXISTS
(SELECT*
FROM SC
WHERE Sno=Student.Sno AND Cno='1');
【eg. 3.55】查询与“刘晨”在同一个系学习的学生,此查询要求可以分布完成
可以用带EXISTS谓词的相关子查询替代
SELECT Sno,Sname,Sdept
FROM Student S1
WHERE EXISTS
(SELECT*
FROM Student S2
WHERE S2.Sdept=S1.Sdept AND S2.Sname='刘晨');
【eg. 3.62】查询选修了全部课程的学生姓名
SELECT Sname
FROM Student
WHERE NOT EXISTS /*返回真值*/
(SELECT *
FROM Course
WHERE NOT EXISTS /*返回真值*/
(SELECT *
FROM SC
WHERE Sno=Student.Sno
AND Cno=Course.Cno)
);
【eg. 3.63】查询了至少选修了学生2018304188选修的全部课程的学生号码
SELECT DISTINCT SCX.Sno
FROM SC SCX
WHERE NOT EXISTS
(SELECT *
FROM SC SCY
WHERE SCY.Sno='2018304188' AND
NOT EXISTS /*选修了学生2018304188选修的全部课程*/
(SELECT *
FROM SC SCZ
WHERE SCZ.Sno=SCX.Sno AND
SCZ.Cno=SCY.Cno)
);
【eg. 3.64】查询计算机科学系的学生及年龄不大于19岁的学生
SELECT *
FROM Student
WHERE Sdept='CS'
UNION
SELECT *
FROM Student
WHERE Sage<=19;
【eg. 3.65】查询选修了课程1或者课程2 的学生
SELECT Sno
FROM SC
WHERE Cno='1'
UNION
SELECT Sno
FROM SC
WHERE Cno='2';
【eg. 3.66】查询计算机系的学生与年龄不大于19岁的学生的交集
SELECT *
FROM Student
WHERE Sdept='CS'
INTERSECT
SELECT *
FROM Student
WEERE Sage<=19;
/*等价于*/
SELECT *
FROM Student
WHERE Sdept='CS' AND Sage<=19;
【eg. 3.67】查询即选修了课程1,又选修了课程2 的学生
SELECT Sno
FROM SC
WHERE Cno='1'
INTERSECT
SELECT Sno
FROM SC
WHERE Cno='2';
/*等价于*/
SELECT Sno
FROM SC
WHERE Cno='1' AND Sno IN
(SELECT Sno
FROM SC
WHERE Cno='2');
【eg. 3.68】查询计算机系的学生与年龄不大于19岁的差集
SELECT *
FROM Student
WHERE Sdept='CS'
EXCEPT
SELECT *
FROM Student
WHERE Sage<=19;
/*实际上是查询计算机系中年龄大于19岁的学生,故等价于*/
SELECT *
FROM Student
WHERE Sdept='CS' AND Sage>19;
语句格式
INSERT
INTO <表名>[(<属性列1>)[,<属性列2>....)]]
VALUES(<常量1>[,<常量2>]...);
功能
INTO子句
VALUES子句
提供的值必须与INTO子句匹配
【eg. 3.69】将一个新学生元组(学号:2018304188;姓名:王;性别:男;所在系:IS;年龄:18)插入到Student表中
INSERT
INTO Student(Sno,Sname,Ssex,Sdept,Sage)
VALUES('2018304188','王','男',IS','18');
【eg. 3.71】插入一条选课记录(‘2018304188’,‘1’).
INSERT
INTO SC(Sno,Cno)
VALUES('2018304188','1');
关系DBMS 将在新插入记录的Grade列上自动赋空值
或者
INSERT
INTO SC
VALUES('201215128','1',NULL);
【eg. 3.70】将学生张成民的信息插入到Student表中
INSERT
INTO Student
VALUES('201215126','张成民','男','18','CS');
语句格式
INSERT INTO<表名>[(<属性列1>)[,<属性列2>...]]
子查询;
INTO子句
子查询
【eg. 3.72】对每个系,求学生的平均年龄,并把结果存入数据库
第一步:建表
CREATE TABLE Dept_age /*表名*/
(Sdept CHAR(15) /*系名*/
AVG_age SMALLINT); /*学生平均年龄*/
第二步:插入数据
INSERT
INTO Dept_age(Sdept,AVG_age)
SELECT Sdept,AVG_age
FROM Student
GROUP BY Sdept;
语句格式
UPDATE<表名>
SET<列名>=<表达式>[,<列名>=<表达式>]...
[WHERE<条件>];
功能
三种修改方式
【eg. 3.73】将学生201215121的年龄改为22岁
UPDATE Student
SET Sage=22
WHERE Sno='201215121';
【eg. 3.74】把所有学生的年龄都增加1
UPDATE Student
SET Sage=Sage+1;
【eg. 3.75】将计算机系全体学生的成绩置为0
UPDATE SC
SET Grade=0
WHERE Sno IN
(SELECT Sno
FROM Student
WHERE Sdept='CS'
);
语句格式
DELETE FROM <表名>
[WHERE<条件>];
功能
WHERE子句
三种删除方式
【eg. 3.76】删除学号为201215128的学生记录
DELETE FROM Student
WHERE Sno='201215128';
【eg. 3.77】删除所有学生选课记录
DELETE FROM SC;
【eg. 3.78】删除计算机系所有学生的选课记录
DELETE
FROM sc
WHERE Sno IN
(SELECT Sno
FROM Student
WHERE Sdept='cs');
空值是一个很特殊的值,含有不确定性。对关系运算带来特殊问题,需要做特殊的处理
空值产生有其实际需要
例如学生在选课中,用空值来表示没选课
【eg. 3.81】找出漏填了性别或者年龄信息的记录
SELECT *
FROM Student
WHERE Ssex IS NULL OR Sage IS NULL;
【eg. 3.82】找出选修一号课程的不及格的学生
SELECT Sno
FROM SC
WHERE Grade<60 AND Cno='1';
查询结果不包括缺考的学生,因为他们的Grade值为NULL
【eg. 3.83】选出课程以号不及格的学生以及缺考的考生
SELECT Sno
FROM SC
WHERE Cno='1' AND (Grade<60 OR Grade IS NULL);
语句格式
CREATE VIEW
<视图名>[(<列名>[,<列名>]...)]
AS <子查询>
[ WITH CHECK OPTION];
WITH CHECK OPTION
子查询可以是任何SELECT 语句,是否含有ORDER BY子句和DISTINCT 短语,则决定具体系统的实现
组成视图的属性列名:全部省略或全部指定
关系DBMS执行CREATE VIEW 语句时,只是把视图定义存入数据字典,并不执行其中的SELECT语句
在对视图查询时,按视图的定义从基本表中将数据查出
【eg. 3.84】建立信息系学生的视图
CREATE VIEW IS_Student
AS
SELECT Sno,Sname,Sage
FROM Student
WHERE Sdept='IS';
【eg. 3.84】建立信息系学生的视图,并要求进行修改和插入操作时任保证该视图只有信息系的学生
CREATE VIEW IS_Studnt
AS
SELECT Sno,Sname,Sage
FROM Student
WHERE Sdept='IS'
WITH CHECK OPTION;
定义IS_Student 视图时加上WITH CHECK OPTION 子句,对该视图进行插入、修改、删除操作时,RDBMS会自动加上Sdept='IS’的条件
若一个视图是从单个基本表中导出的,并且只是去掉了基本表的某些行和某些列,但保留了主码,我们称这类视图为行列子集视图
基于多个表的视图
【eg. 3.86】建立信息系选修了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';
【eg. 3.87】建立信息系选修了1号课程且成绩在90分以上的学生的视图
CREATE VIEW IS_S2
AS
SELECT Sno,Sname,Grade
FROM IS_S1
WHERE Grade>=90;
【eg. 3.88】定义一个反映学生出生年份的视图
CREATE VIEW BT_S(Sno,Sname,Sbirth)
AS
SELECT Sno,Sname,2020-Sage
FROM Student;
【eg. 3.89】将学生的学号及平均成绩定义为一个视图
CREATE VIEW S_G(Sno,Gavg)
AS
SELECT Sno,AVG(Grade)
FROM SC
GROUP BY Sno;
【eg. 3.90】将Student表中所有女生记录定义为一个视图
CREATE VIEW F_Student(F_Sno,name,sex,age,dept)
AS
SELECT * /*没有不指定属性列*/
FROM Student
WHERE Ssex='女';
缺点:修改基本表Student的机构后,Student表与F_Student视图的映像关系被破坏,导致视图不能正确工作
语句的格式
DROP VIEW <视图名>[CASCADE]
【eg. 3.91】删除视图BT_1和IS_S1
DROP VIEW BT_S; /*成功执行*/
DROP VIEW IS_S1; /*拒绝执行*/
要删除IS_S1 需使用级联删除:
DROP VIEW IS_S1 CASCADE;
【eg. 3.92】在信息系学生的视图中找出年龄小于20岁的学生
SELECT Sno,Sage
FROM Student
WHERE Sage<20;
视图消极转换后的查询语句为
SELECT Sno,Sage
FROM Student
WHERE Sdept='IS' AND Sage<20;
【eg. 3.93】查询选修了课程1号的信息系学生
SELECT IS_Student.Sno,Sname
FROM IS_Student,SC
WHERE IS_Student.Sno=SC.Sno AND SC.Cno='1';
【eg. 3.94】在S_G 视图中查询平均成绩在90分以上的学生学号和平均成绩
SELECT *
FROM S_G
GROUP BY Sno
HAVING Gavg>=90;
/*S_G视图的定义如下*/
CREATE VIEW S_G(Sno,Gavg)
AS
SELECT Sno,AVG(Grade)
FROM SC
GROUP BY Sno;
也可以用SQL语句完成
SELECT *
FROM (SELECT Sno,AVG(Grade)
FROM SC
GROUP BY Sno)
AS
S_G(Sno,Gavg)
WHERE Gavg>=90;
【eg. 3.95】将信息系学生视图IS_Student中学号为2018304188的学生姓名改为小王
UPDATE IS_Student
SET Sname='小王'
WHERE Sno='2018304188';
转换后的语句
UPDATE Student
SET Sname='小王'
WHERE Sno='2018304188' AND Sdept='IS';
【eg. 3.96】向信息系学生视图IS_Student 中插入一个新的学生记录,其中学号为“2018304188”,姓名为小郑,年龄为20岁
INSERT
INTO IS_Stdent(Sno,Sname,Sage)
VALUES('2018304188','小郑','20');
转换为对基本表的更新
INSERT
INTO Student(Sno,Sname,Sage,Sdept)
VALUES('2018304188','小郑','20','IS');
【eg. 3.97】删除信息系学生视图IS_Student中学号为2018304188的记录
DELETE
FROM IS_Student
WHERE Sno='2018304188'
转换为对基本表的更新
DELETE
FROM Student
WHERE Sno='2018304188' AND Sdept='IS';
更新视图的限制:有一些视图是不可更新的,因为对这些视图的更新不能唯一的有意义的转换称对相应基本表的更新
允许对行列子集视图(单表上的视图)进行更新
对其他类型的视图的更新不同系统由不同限制
DB2对视图的更新的限制