参考文献链接1(基本介绍)
参考文献链接2(复习例题)
参考资料3:中国大学MOOC——中国人民大学“数据库系统概论”
SQL语言种类 | 操作 |
---|---|
DDL 数据定义语言 | create(创建) drop(删除) alte(修改) |
DQL 数据查询语言 | select(查询) |
DML 数据操纵语言 | insert(插入) update(更新) delete(删除) |
DCL 数据控制语言 | grant(授予) revoke(吊销) |
视图链接
SQL语言种类 | 操作 |
---|---|
DDL 数据定义语言 | create(创建) drop(删除) alte(修改) |
DQL 数据查询语言 | select(查询) |
DML 数据操纵语言 | insert(插入) update(更新) delete(删除) |
DCL 数据控制语言 | grant(授予) revoke(吊销) |
p(精度):小数点两边的总位数
s(小数位数):小数点右边的位数
create table <表名1> (<字段1 数据类型 约束>,<字段2 数据类型 约束>,primary key(字段1,字段2) )
eg:
create table Room(
roomNo char(10) primary key,
hotelNo char(10) default ‘0000000000’,
type char(10) not null,
price char(10) not null check(price>=100),
foreign key(hotelNo) references Hotel(hotelNo)
);
//若primary key是由多个属性组成则
//表级约束性条件加上 primary key(A,B),
drop table <表名>
eg:
ALTER TABLE Course DROP CONSTRAINT 自定义的约束名
//删除属性的某约束条件,约束名是用户自定义的
//add语句 添加 列
alter table <表名> add <列名 数据类型 约束>
//alter语句 修改约束条件或数据类型
alter table <表名> alter column <列名> <数据类型> <约束>
eg:
alter table Course add unique (Cname)//未自定义约束条件约束名
ALTER TABLE Course ADD constraints aaa UNIQUE(Cname)//自定义约束条件约束名
alter table Student alter column Sage int
—
CREATE INDEX [UNIQUE / CLUSTER] 索引名 ON 表名(
列名 [次序]
[,列名 [次序] ]
);
eg:
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 数据表名.索引
eg:
Drop index S_idx
create database 数据库名称
on(
name=数据文件逻辑名称,
filename='路径+数据文件名',
size=数据文件初始大小,
maxsize=数据文件的最大容量,
filegrowth=数据文件自动增长量,
)
[log on(
name = 日志文件逻辑名称,
filename='路径+日志文件名',
size=数据文件初始大小,
maxsize=数据文件的最大容量,
filegrowth=数据文件自动增长量,
)]
ADD FILE :向数据库添加数据文件
alter database 数据库名称
add file(
name=数据文件逻辑名称,
filename='路径+数据文件名',
size=数据文件初始大小,
maxsize=数据文件的最大容量,
filegrowth=数据文件自动增长量,
)
ADD LOG FILE :向数据库添加日志文件
REMOVE FILE:从数据库删除逻辑文件,并删除物理文件。无法删除文件组不为空的文件。
MODIFY FILE:指定要修改的文件
drop database 数据库名称
SELECT [ALL|DISTINCT] <目标列表达式>[,<目标列表达式>] ...
FROM <表名或视图名>[,<表名或视图名> ]...|(SELECT 语句) [AS]<别名>
[ WHERE <条件表达式> ]
[ GROUP BY <列名1>
[ HAVING <条件表达式> ] ]
[ ORDER BY <列名2> [ ASC|DESC ] ];
/*
SELECT子句:指定要显示的属性列
FROM子句:指定查询对象(基本表或视图)
WHERE子句:指定查询条件
GROUP BY子句:对查询结果按指定列的值分组,该属性列值相 等的元组为一个组。通常会在每组中作用聚集函数。
HAVING短语:只有满足指定条件的组才予以输出
ORDER BY子句:对查询结果表按指定列值的升序或降序排序
*/
//投影该表的所有信息:
select * from 表名
// * 代指原表中的所有列 且顺序都和原表一致
eg:
//查询全体学生的详细记录
SELECT Sno,Sname,Ssex,Sage,Sdept FROM Student;
//或
SELECT * FROM Student;
表达式使用了函数的查询
//SELECT 子句的 <目标列表达式> 不仅可以为表中的 属性列,也可以是 表达式 或 函数
eg: lower() 小写函数 ;date() 日期函数 ;year()取年份
//查全体学生的姓名及其出生年份,Sname是隐含条件列
SELECT Sname,2016-Sage FROM Student;
//or
select Sname,year(data())-Sage from Student;
//查询全体学生的姓名、出生年份和所在的院系,要 求用小写字母表示系名。
SELECT Sname,'Year of Birth: ',2014-Sage,LOWER(Sdept) FROM Student;
//输出结果:
Sname 'Year of Birth:' 2014-Sage LOWER(Sdept)
李勇 Year of Birth: 1944 cs
刘晨 Year of Birth: 1955 ma
使用列别名改变查询结果的列标题
select <列名> 空格 <自定义别名>
[,<列名> 空格 <自定义别名>,]
from <表名>;
//或
select <列名> as <自定义别名>
[,<列名> as <自定义别名>,]
from <表名>;
eg:
SELECT Sname NAME,
'Year of Birth:' BIRTH,
2014-Sage BIRTHDAY,
LOWER(Sdept) DEPARTMENT
FROM Student;
//输出结果:
NAME BIRTH BIRTHDAY DEPARTMENT
李勇 Year of Birth: 1944 cs
刘晨 Year of Birth: 1955 ma
省略 值 重复的行
//如果没有指定DISTINCT关键词,则缺省为ALL ,ALL即为不取消重复的元组
SELECT DISTINCT <目标列表达式>
[,<目标列表达式>] FROM <表名或视图名>;
eg:
//查询选修了课程的学生学号:
//默认 ALL 时
SELECT Sno FROM SC;
//结果为:
Sno
201215121
201215121
201215121
201215122
201215122
// DISTINCT 时
SELECT DISTINCT Sno FROM SC;
//结果为:
Sno
201215121
201215122
where + 对元组某一属性进行限制的条件
与直接在select F(列名) 的区别在于,where 对元组的某一属性进行的限制可以不对限制条件的属性进行输出,而select后的所有属性都要有输出
select <列名,[列名2]…> from 表名 where 条件
//查询考试成绩有不及格的学生的学号
SELECT DISTINCT Sno
FROM SC
WHERE Grade<60;
//查询年龄不在20~23岁之间的学生姓名、系别和年龄
SELECT Sname, Sdept, Sage
FROM Student
WHERE Sage NOT BETWEEN 20 AND 23;
//查询既不是计算机科学系、数学系,也不是信息系 的学生的姓名和性别。
SELECT Sname, Ssex
FROM Student
WHERE Sdept NOT IN ('IS','MA’,'CS' );
<匹配串>可以是一个完整的字符串,也可以含有通配符%和 _
% (百分号) 代表任意长度(长度可以为0)的字符串 例如a%b表示以a开头,以b结尾的任意长度的字符串
_ (下横线) 代表任意单个字符。 例如a_b表示以a开头,以b结尾的长度为3的任意字符串
如需输出%或_则可以使用 / 或者[]进行 转意符
用/转义: 每一个条件后面需要加 escape ‘/’
用[]转义:直接在写条件时候在[]输入原本意义的字符
//1.匹配串为固定字符串:
//查询学号为201215121的学生的详细情况
select *
from SC
where Sno like ‘201215121’;
//2.匹配串为含通配符的字符串:
//查询所有姓刘学生的姓名、学号和性别
SELECT Sname, Sno, Ssex
FROM Student
WHERE Sname LIKE ‘刘%’;
//3.匹配串为含通配符的字符串:
//查询姓"欧阳"且全名为三个汉字的学生的姓名
SELECT Sname
FROM Student
WHERE Sname LIKE ‘欧阳__’;
//4.使用换码字符将通配符转义为普通字符:
//查询以"DB_"开头,且倒数第3个字符为 i的课程的详细情况。
SELECT *
FROM Course
WHERE Cname LIKE 'DB/_%i_ _' ESCAPE '/' ;
//ESCAPE '/' 表示“ /” 为换码字符
SELECT *
FROM Course
WHERE Cname LIKE 'DB[_]%i_ _';
//某些学生选修课程后没有参加考试,所以有选课记 录,但没 有考试成绩。
//查询缺少成绩的学生的学号和相应的课程号
SELECT Sno,Cno
FROM SC
WHERE Grade IS NULL
//查询计算机系年龄在20岁以下的学生姓名。
SELECT Sname
FROM Student
WHERE Sdept= 'CS' AND Sage<20;
注意是order by 不是 group by
对结果进行排序,要写在最后
可以按一个或多个属性列排序
升序:ASC;(default为ASC)
降序:DESC;
对于空值,排序时显示的次序由具体系统实现来 决定
//查询选修了3号课程的学生的学号及其成绩,查询结果按分数降序排列。
SELECT Sno, Grade
FROM SC
WHERE Cno='3'
ORDER BY Grade DESC;
//查询全体学生情况,查询结果按所在系的系号升序排列,同一系中的学生按年龄降序排列。
SELECT *
FROM Student
ORDER BY Sdept ASC, Sage DESC;
//查询学生总人数
SELECT COUNT(*)
FROM Student;
//查询选修了课程的学生人数
SELECT COUNT(DISTINCT Sno)
FROM SC;
//计算1号课程的学生平均成绩
SELECT AVG(Grade)
FROM SC
WHERE Cno= ' 1 ';
//查询选修1号课程的学生最高分数
SELECT MAX(Grade)
FROM SC
WHERE Cno='1';
//查询学生201215012选修课程的总学分数
SELECT SUM(Ccredit)
FROM SC,Course
WHERE Sno='201215012' AND SC.Cno=Course.Cno;
注意是group by 不是order by
细化聚集函数的作用对象:
HAVING短语与WHERE子句的区别:
SELECT 目标列表达式, 集函数(列名)
FROM 表名
[WHERE 条件表达式]
[GROUP BY 分组条件表达式]
[ORDER BY 列名];
//求各个课程号及相应的选课人数
SELECT Cno,COUNT(Sno)
FROM SC
GROUP BY Cno;
//查询结果可为:
Cno COUNT(Sno)
1 22
2 34
3 44
4 33
5 48
//查询选修了3门以上课程的学生学号。
SELECT Sno
FROM SC
GROUP BY Sno
HAVING COUNT(*) >3;
join
(1)inner join(内连接)
(2)left (outer) join 左(外)连接 --以左边的表为基准(右边缺乏数据为null)
(3)right (outer) join 右(外)连接 --以右边的表为基准(左边缺乏数据为null)
(4)full (outer) join 完整(外)连接(缺乏数据为null)
//查询每个学生及其选修课程的情况
SELECT Student.*, SC.*
FROM Student, SC
WHERE Student.Sno = SC.Sno;
//结果:
Student.Sno Sname Ssex Sage Sdept SC.Sno Cno Grade
201215121 李勇 男 20 CS 201215121 1 92
201215121 李勇 男 20 CS 201215121 2 85
201215121 李勇 男 20 CS 201215121 3 88
201215122 刘晨 女 19 CS 201215122 2 90
201215122 刘晨 女 19 CS 201215122 3 80
没有自然连接的运算符,故直接输入自然连接后的列名称
//自然连接
SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student,SC
WHERE Student.Sno = SC.Sno;
嵌套循环法(NESTED-LOOP)
排序合并法(SORT-MERGE)
索引连接(INDEX-JOIN)
//查询选修2号课程且成绩在90以上的所有学生的姓名和学号
SELECT Student.Sno, Sname
FROM Student, SC
WHERE Student.Sno=SC.Sno //连接谓词
AND SC.Cno=' 2 ' AND SC.Grade>90;//选择谓词
//查询每一门课的直接先修课的名称
SELECT FIRST.Cname,SECOND.Cname
FROM Course FIRST, Course SECOND
WHERE FIRST.Cpno = SECOND.Cno;
//表
课程号Cno 课程名Cname 先行课Cpno 学分Ccredit
1 数据库 5 4
2 数学 2
3 信息系统 1 4
4 操作系统 6 3
5 数据结构 7 4
6 数据处理导论 2
7 C语言 6 4
//结果:
First.Cname Second.Cname
数据库 数据结构
信息系统 数据库
操作系统 数据结构
数据结构 C语言
C语言 数据处理导论
(1)left (out) join 左(外)连接 --以左边的表为基准(右边缺乏数据为null)
(2)right (out) join 右(外)连接 --以右边的表为基准(左边缺乏数据为null)
(3)full (out) join 完整(外)连接(缺乏数据为null)
//查询每个学生及其选修课程的情况
SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student left out join SC ON(Student.Sno=SC.Sno);
//有些商业系统的表达更简单:
SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student,SC
WHERE Student.Sno(+) =SC.Sno;
//结果:
Student.Sno Sname Ssex Sage Sdept Cno Grade
201215121 李勇 男 20 CS 1 92
201215121 李勇 男 20 CS 2 85
201215121 李勇 男 20 CS 3 88
201215122 刘晨 女 19 CS 2 90
201215122 刘晨 女 19 CS 3 80
201215123 王敏 女 18 MA NULL NULL
201215125 张力 男 19 IS NULL NULL
多表连接:两个以上的表进行连接
//查询每个学生的学号、姓名、选修的课程名及成绩
SELECT Student.Sno, Sname, Cname, 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 ');
eg1:
//查询与“刘晨”在同一个系学习的学生。此查询要求可以分步来完成
//1 确定“刘晨”所在系名
SELECT Sdept
FROM Student
WHERE Sname= ' 刘晨 ';
//结果为: CS
//2 查找所有在CS系学习的学生。
SELECT Sno, Sname, Sdept
FROM Student
WHERE Sdept= ' CS ';
//结果为:
Sno Sname Sdept
201215121 李勇 CS
201215122 刘晨 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 = '刘晨';
eg2:
//查询选修了课程名为“信息系统”的学生学号和姓名
SELECT Sno,Sname //3 最后在Student关系中 取出Sno和Sname
FROM Student
WHERE Sno IN
(SELECT Sno //2 然后在SC关系中找出选 修了3号课程的学生学号
FROM SC
WHERE Cno IN
(SELECT Cno //1 首先在Course关系中找出 “信息系统”的课程号,为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='信息系统';
当能确切知道内层查询返回单值时,可用比较运算符(>,<,=,>=,<=,!=或< >)
eg1:
//查询与“刘晨”在同一个系学习的学生。
SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept = /*由于一个学生只可能在一个系学习 , 用=代替*/
(SELECT Sdept
FROM Student
WHERE Sname= '刘晨');
eg2:
//找出每个学生超过他选修课程平均成绩的课程号。
SELECT Sno, Cno
FROM SC x //相关子查询
WHERE Grade >=
(SELECT AVG(Grade)
FROM SC y
WHERE y.Sno=x.Sno);
//可能的执行过程
//从外层查询中取出SC的一个元组x,将元组x的Sno值 (201215121) 传送给内层查询。
SELECT AVG(Grade)
FROM SC y
WHERE y.Sno='201215121‘;
//执行内层查询,得到值88(近似值),用该值代替内层查询,得到外层查询:
SELECT Sno,Cno
FROM SC x
WHERE Grade >=88;
//执行该查询,得到结果:
(201215121,1)
(201215121,3)
//然后外层查询取出下一个元组重复做上述1至3 步骤,直到外层的SC元组全部处理完毕。
//结果为:
(201215121,1)
(201215121,3)
(201215122,2)
在谓词逻辑中,还有存在量词和全称量词的概念,在SQL中并没有对应的表达,统一采用“谓词” 来表达
- 方法一:
引入ANY和ALL谓词,其对象为某个查 询结果,表示其中任意一个值或者全部值
- 方法二:
引入EXIST谓词,其对象也是某个查询结 果,但表示这个查询结果是否为空,返回真值。
使用ANY或ALL谓词时必须同时使用比较运算
语义为:
> ANY 大于子查询结果中的某个值
> ALL 大于子查询结果中的所有值
< ANY 小于子查询结果中的某个值
< ALL 小于子查询结果中的所有值
>= ANY 大于等于子查询结果中的某个值
>= ALL 大于等于子查询结果中的所有值
<= ANY 小于等于子查询结果中的某个值
<= ALL 小于等于子查询结果中的所有值
= ANY 等于子查询结果中的某个值
= ALL 等于子查询结果中的所有值(无意义)
!=(或<>)ANY 不等于子查询结果中的某个值
!=(或<>)ALL 不等于子查询结果中的任何一个值
//ANY(或SOME),ALL谓词与聚集函数、IN谓词的等 价转换关系
= <>或!= < <= > >=
ANY IN <MAX <=MAX >MIN >= MIN
ALL NOT IN <MIN <= MIN >MAX >= MAX
eg1:
//查询非计算机科学系中比计算机科学系任意一个学生年龄小的学生姓名和年龄
SELECT Sname,Sage
FROM Student
WHERE Sage < ANY
(SELECT Sage
FROM Student
WHERE Sdept= ' CS ')
AND Sdept <> ‘CS ' ; //父查询块中的条件
//结果:
Sname Sage
王敏 18
张立 19
//执行过程:
(1)首先处理子查询,找出CS系中所有学生的年龄,构成一个 集合(20,19)
(2)处理父查询,找所有不是CS系且年龄小于20 或 19的学生
//用聚集函数实现
SELECT Sname,Sage
FROM Student
WHERE Sage <
(SELECT MAX(Sage)
FROM Student
WHERE Sdept= 'CS ')
AND Sdept <> ' CS ';
eg2:
//查询非计算机科学系中比计算机科学系所有学 生年龄都小的学生姓名及年龄。
//方法一:用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 ';
EXISTS谓词
eg1:
//查询所有选修了1号课程的学生姓名。
//思路分析:
//1.本查询涉及Student和SC关系
//2.在Student中依次取每个元组的Sno值,用此值去检查SC表
//3.若SC中存在这样的元组,其Sno值等于此Student.Sno值, 并且其Cno= ‘1’,则取此Student.Sname送入结果表
SELECT Sname
FROM Student
WHERE EXISTS
(SELECT *
FROM SC
WHERE Sno=Student.Sno AND Cno= ' 1 ');
eg2:
//查询没有选修1号课程的学生姓名
SELECT Sname
FROM Student
WHERE NOT EXISTS
(SELECT *
FROM SC
WHERE Sno = Student.Sno AND Cno='1');
eg1:
//查询与“刘晨”在同一个系学习的学生。可以用带EXISTS谓词的相关子查询替换:
SELECT Sno,Sname,Sdept
FROM Student S1
WHERE EXISTS
(SELECT *
FROM Student S2
WHERE S2.Sdept = S1.Sdept AND S2.Sname = '刘晨');
eg2:
//查询选修了全部课程的学生姓名。
SELECT Sname
FROM Student WHERE NOT EXISTS
(SELECT *
FROM Course WHERE NOT EXISTS
(SELECT *
FROM SC
WHERE Sno= Student.Sno
AND Cno= Course.Cno ));
用EXISTS/NOT EXISTS实现逻辑蕴涵(难点)
eg:
查询至少选修了学生201215122选修的全部课程的 学生号码。
解题思路:
用逻辑蕴涵表达该查询:
用P表示谓词 “学生201215122选修了课程y”
用q表示谓词 “学生x选修了课程y”
则上述查询为: (y) p → q对(所有的课程y,只要201215122学生选修了课程y,则x也选修了y)
变换后语义:
不存在这样的课程y,学生201215122选修了 y,而学生x没有选。
SELECT DISTINCT SCX.Sno
FROM SC SCX
WHERE NOT EXISTS
(SELECT * // P & Not(Q)
FROM SC SCY
WHERE SCY.Sno = ' 201215122 ' AND
NOT EXISTS
(SELECT *
FROM SC SCZ
WHERE SCZ.Sno=SCX.Sno AND SCZ.Cno=SCY.Cno));
参加集合操作的各查询结果的列数必须相同;对应项的数据类型也必须相同
eg1:
//查询计算机科学系的学生及年龄不大于19岁的学生
SELECT *
FROM Student
WHERE Sdept= 'CS'
UNION
SELECT *
FROM Student
WHERE Sage<=19;
//UNION:将多个查询结果合并起来时,系统自动去掉重复元组
//UNION ALL:将多个查询结果合并起来时,保留重复元素
eg2:
//查询选修了课程1或者选修了课程2的学生。
SELECT Sno
FROM SC
WHERE Cno=' 1 '
UNION
SELECT Sno
FROM SC
WHERE Cno= ' 2 ';
eg1:
//查询计算机科学系的学生与年龄不大于19岁的学生的交集。
SELECT *
FROM Student
WHERE Sdept='CS'
INTERSECT
SELECT *
FROM Student
WHERE Sage<=19
//实际上就是查询计算机科学系中年龄不大 于19岁的学生。
SELECT *
FROM Student
WHERE Sdept= 'CS' AND Sage<=19;
eg2:
//查询既选修了课程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 ');
eg1:
//查询计算机科学系的学生与年龄不大于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 <表名> [列名,[<列名>,<列名>…]]
eg:
insert into Hotel values(‘H1035’,‘前进宾馆’,‘长春’);
delete from 表名 where 条件
eg:
delete from Booking where dateTo=‘20171202’);
update 表名 set 列名=值 where 条件
eg:
update Room set type = ‘单人间’
where roomNo = ‘369’ and hotelNo in
(select hotelNo from Hotel where hotelName = ‘长春宾馆’);