一、关系代数的五个基本操作
分析:题目中出现找条件一般就用选择(学号在一定范围,性别男还是女,年龄在什么范围…)
例:①查询信息系(IS系)全体学生
δ sdept=‘IS’(Student)
②查询年龄小于20的学生
δ Sage<20(Student)
例:①查询学生的姓名和所在的系
分析:姓名,所在系是两个属性
Π Sname,Sdept(Student)
②查询学生关系Student中都有哪些系
分析:所在系的属性
Π Sdept(Student)
③查询选修了2号课程的学生的学号
分析:选择-2号课程(条件);投影-学号(属性) 注意:要先做条件,再做属性
ΠSno(δCno=‘2’(SC))={201215121,201215122}
3.笛卡尔乘积(X):把两个关系拼接(把两个表每一个元组两两拼接在一起)
4.集合差(-):集合中减法
5.集合并(∪):将2个关系中模式相同的元组并起来
二、常用操作
(1)条件连接:表1▷◁表2=δ条件(表1X表2)(先按条件完成笛卡尔乘积,再连接)
(2)等值连接:若(1)中条件都是想等判断,则是等值连接(对两个表做笛卡尔乘积之后,按照相等的条件筛选出来)
(3)▲自然连接:2张表在它们所有的公共属性上做等值连接,并把结果中重复的列去掉
(4)外连接
①左外连接:把连接运算符左边的所有元组都保留下来,不匹配的元组在右边补空值
②右外连接:把连接运算符右边的所有元组都保留下来,不匹配的元组在左边补空值
③外连接:把所有元组都保留下来
连接的作用:所查询信息需要多个表
例:查至少选修一门其直接先行课为5号课程的学生姓名
分析:
看到一个学生表里面的信息不全,没有公共属性;没有课程相关的,所以要先将学生表与课程表Course还有连接在一起,还有SC表这三个表连接起来
选修一门直接先行课为5号课 δcpno=5,查学生姓名但这个课程表并没有学生姓名,所以先对SC表做连接找到5号课对应的课程号,根据课程号能找到对应的学号(属性)
条件:选修一门直接先行课为5号课 δcpno=5(course)
投影:5号课对应的课程号 Πsno
学号对应的学生姓名 Πsno,sname(Student)
Πsname( Πsno(δcpno=‘5’(course)▷◁Πsno,sname(Student))
或者 Πsname(δcpno=‘5’(course)▷◁SC▷◁Πsno,sname(Student))
同时从行和列的角度运算
条件:查找所有、全部、至少…
除运算一般在一个表中是查不出来的(要是能查出来就用不到除运算)
举例:
除运算:要有公共的属性才能做除法 a:被除数,b:除数(全部覆盖)
首先两表相除要有公共属性,除法的作用是找出被除数中是否有一个或几个元组(除公共属性之外的元组),与除数中所有相关属性,(a和b的公共属性)都有关联,往往全部…作为除数,而所查的信息(属性)作为被除数
例:查询选修了全部课程的学生号码和姓名
分析:
投影:号码和姓名(属性)
除法:全部课程(覆盖)
连接:需要两个表连接在一起
Πsno,cno(SC)÷Πcno(Course)▷◁ Πsno,Sname(Student)
三、SQL查询
select [distinct] (去重)所查内容 from 所查询的表(可多个)where 要求条件
例:查计算机科学系全体学生
select Sname from Student where Sdept=‘CS’;
查询所有年龄在20岁以下的学生的学号和年龄
select Sno,Sage from Student where Sage<20;
(1)范围
①between … and … 在…之间
例:查询年龄在20岁~30岁之间的学生姓名、系别和年龄
select Sname,Sdept,Sage from Student where Sage between 20 and 30;
②not between…and… 不在…之间
例:查询年龄不在20岁~30岁之间的学生姓名、系别和年龄
select Sname,Sdept,Sage from Student where Sage not between 20 and 30;
(2) 确定集合
①in:查找属性值属于指定集合的元组(相当于数学中的属于€)
例:查询计算机科学系(CS)、数学系(MA)、信息系(IS)学生的姓名和性别
select Sname,Ssex from Student where Sdept in(‘CS’,‘MA’,‘IS’);
②not in:查找属性值不属于指定集合的元组
查询不是计算机科学系(CS)、数学系(MA)、信息系(IS)学生的姓名和性别
select Sname,Ssex from Student where Sdept not in(‘CS’,‘MA’,‘IS’);
(3)like 模糊查询
①%:表示任意长度
例:查询所有姓刘的学生的姓名、学号和性别
select Sname,Sno,Ssex from Student where Sname like ‘刘%’;
②_:表示任意单个字符
例:查询姓’欧阳’且全名为三个汉字的姓名和学号
select Sname,Sno from Student where Sname like ‘欧阳_’;
③若想查的字符本身含有_或%,则在_前加入\(空格) ‘ESCAPE’ \ '(换码字符):作用是将\后面的_ 转为普通字符,不表示通配符含义
例:查询以“DB_”开头,且倒数第三个字符为i的课程的详细情况
select * from Course where Cname like ‘DB\ _ %i_ _’ ESCAPE ’ \ ';
①and :查询满足and两边的条件
例:查询计算机科学系年龄在20岁以下的学生姓名
select Sname from Student where sdept=‘CS’ and Sage<20;
②or:查询结果满足两边一个条件就可以
例:查询计算机科学系(CS)、数学系(MA)、信息系(IS)学生的姓名和性别
select Sname,Ssex from Student where Sdept=‘CS’ or Sdept=‘MA’ or Sdept=‘IS’;
③not:否定
(5)
①is null(null:表示不确定)
例:某些学生选修课程后没有参加考试,所以有选修记录,但没有考试成绩。查询缺少成绩的学生的学号和相应的课程号。
select Sno,Cno from SC where Grade is null;
②is not null
查询所有有成绩的学生的学号和相应的课程号。
select Sno,Cno from SC where Grade is not null;
例:查询学生总人数
select count (*) from Student
(2)count([distinct] A):计算属性A有多少个值(加[distinct]表示有多少个不同的值)
例:查询选修了课程的学生数
select count(distinct Sno) from Sc;这里的distinct表示一个人选多门课程,但是只记录1次
(3)sum([distinct] A):A的属性上所有元组加一起求和(必须为数值型)
例:查询学生201215012选修课程的总学分数
select sum(Credit) from Sc,Course where Sno=‘201215012’ and Sc.Cno=Couse.Cno;
(4)avg([distinct] A):对A的属性上所有元组求平均值(必须为数值型)
例:计算选修1号课程的学生平均成绩
select avg(grade) from Sc where Cno=‘1’;
(5)max([distinct] A):求属性A的最大值
例:查询选修1号课程的学生最高分数
select max(grade) from Sc where Cno=‘1’;
(6)min([distinct] A):求属性A的最小值
select [distinct] 所查内容
from 所查询的表(可多个)
where 条件或链接或嵌套
group by 属性 对属性相同的值进行1列或多列分组
having 条件 对group by得到的组进行筛选
order by_(desc:对查询结果的一个或多个属性升序(降序排列))
例:求各个课程号及相应选课人数
select Cno,count(Sno) from Sc group by Cno;
这里的Sno用于识别是哪一门课程;group by ;分组Cno;cno组标签
例:查询平均成绩大于等于90分的学生学号和平均成绩
select sno,avg(grade) from Sc group by sno having avg(grade)>=90;
错误语句:
select sno,avg(grade) from Sc where avg(grade)>=90 group by sno;
注:where不能用聚集函数作为条件表达式的
(1)用法:所查询信息不能在一个表中查出来,将多个表连接
(2)等值连接:运算符= ;非等值连接:其他运算符>、<…
例:查询每个学生及其选修课程的情况
select student.* ,sc.* from student,sc where student.sno=sc.sno;
(3)自然连接:在等值连接的基础上把重复属性列去掉
例:查询每个学生及其选修课程的情况
select student.sno,sname,ssex,sage,sdept,cno,grade from student,sc where studen,sno=sc.sno;
这里的Sno两个表中都有,注意区分
(4)自身连接:自己与自己做笛卡尔积,再按连接条件做选择操作
第一个表的每一行元组与第二个表的所有行元组拼接
例:查询每一门课程的间接先行课(先行课的先行课)
select first.cno,second.cpno from course first,course second where first.cpno=second.cno;
(5)外连接:悬浮元组保存在结果关系中
(6)多表连接:涉及到查询的结果在多个表中,需要将多表连接在一起
例:查询每个学生的学号、姓名、选修课程名及成绩
select Student,Sname,Cname,grade from Student,Sc,Course where Student.Sno=SC.sno and Sc.cno=Course.cno;找公共属性,snocno将Sc表和Course表和student拼接在一起
(1)分类
⑴不相关子查询:子查询的查询条件不依赖于父查询
例①:查询选修了2号课程的学生姓名
第一步找课程号为2的学生的学号,假设这里理解为一个集合它是包含课程号为2的所有学生的学号; select sno from student where cno=‘2’;然后再在这个集合里面找对应学号的学生姓名 select sname from student where sno;
这两个用IN连接,表示嵌套
select sname from student where sno IN (select sno from student where cno=‘2’);
例:②查询选修了课程名为“信息系统”的学生学号和姓名
解法1:因为信息系统课在Course表里面,而学生姓名和学号在Student表中,两者没有公共属性无法用连接查询,所以要借助SC表作为中间关系找到公共属性将两个表连接起来,这样就变为3表连接
select student.sno,sname from student,sc,course where student.sno=sc.sno and sc.cno=course.cno and course.cname=‘信息系统’;
解法2:第一步先找课程名为信息系统的课程号select cno from course where cname=‘信息系统’;其次在SC表中找选修了信息系统的学号select sno from sc where cno;这样就可以知道那各学号选修了信息系统这门课最后找学号所对应的学生姓名select sno,sname from student where sno,将这3个用IN做嵌套
select sno,sname from student where sno IN (select sno from sc where cno IN (select cno from course where cname=‘信息系统’));
⑵相关子查询:子查询的查询条件依赖于父查询
例:找出每个学生超过他自己选修课程平均成绩的课程号
第一步先找课程号select cno from sc x(x别名);第二步在表中查平均成绩select avg(grade) from sc y(y别名)
sno:作用标注哪个学生超过他平均成绩
y.sno=x.sno相关子查询,查询的y的学号依赖于父查询x
每个学生都有自己的平均成绩,子查询要查询的平均成绩要依赖于父查询对应的哪个学生查
select sno,cno from sc x where grade>=(select avg(grade) from sc y where y.sno=x.sno);
(2)in
(3)比较运算符
(4)any,all谓词子查询
>any 大于子查询结果中某个值
>all 大于子查询结果中所有值
<>any不等于子查询结果中某个值
<>all不等于子查询结果中任何一个值
例:查询非计算机科学系中比计算机科学系所有学生年龄都小的学生姓名及年龄
这里的计算机科学系是一个参照体
select sname,sage from student where sage<All (select sage from student where sdept=‘CS’) and sdept <> ‘CS’;
(5)谓词子查询
⑴exists(存在)
⑵not exists(不存在)
例:查询没有选修1号课程的学生姓名
select sname from student where not exists(select * from sc where sno=student.sno and cno=‘1’);
select * from sc where sno=student.sno and cno=‘1’;是指查询选修了1号课程的信息,而题目要求查询不是选修1号课程的信息,所以取它的补集就是没有选修1号课程的信息
*:表示查询一个表中的所有信息
例:查询既选修了1号课程又选修了2号课程的学生。
既选1号课程又选2号课程select sno from sc where cno=‘1’; and cno=2;这是错误的,不能保证所查的属性既是1号课程又是2号课程,采用集合交,第1步找选修了1号课程select sno from sc where cno=‘1’;第2步找选修了2号课程select sno from sc where cno=‘2’;将两个条件交,度保证能够满足。
select sno from sc where cno=‘1’ INTERSECT select sno from sc where cno=‘2’;
(2)union(并):满足一个条件
例:查询选修了1号课程或者选修了2号课程的学生。
或者;采用集合并,第1步找选修了1号课程select sno from sc where cno=‘1’;第2步找选修了2号课程select sno from sc where cno=‘2’;将两个条件并,满足其中1个即可。
select sno from sc where cno=‘1’ UNION select sno from sc where cno=‘2’;
(3)except(差):
例:查询计算机科学系的学生与年龄不大于19岁的学生的差集。
直接将两个语句用EXCEPT连接
select * from student where sdept=‘CS’ EXCEPT select * from student where sage<=19;
子查询不仅可以出现在where子句中,还可以出现在from子句中,这时子查询生成临时派生表成为主查询的查询对象。
(1)插入元组
insert into 表名(属性1,属性2…)values (‘值1’,‘值2’…)
值和属性要一 一对应
例:将一个新学生元组(学号:121200,姓名:陈东,性别:男,所在系:IS,年龄:18岁)插入student表中
insert into student(sno,sname,ssex,sdept,sage) values (‘121200’,‘陈冬’,‘男’,‘IS’,18);
若有属性,而没有对应的值要写NULL(赋空值)
(2)插入子查询结果
insert into 表名(属性1,属性2…)子查询
例:对每一个系,求学生的平均年龄,并把结果存入数据库
先建一个新表,一列存放系名,另一列存放学生平均年龄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);
(1)update 表名 set 属性(修改的值)where 条件
例:将学生201200的年龄改为22岁
update student set sage=22 where sno=‘201200’;
(2)带子查询的修改 IN
例:将计算机科学系全体学生成绩置0.
两个不同的表,先找在计算机科学系的学生学号,然后再将学号置为0
update sc set grade=0 where sno IN (select sno from student where sdept=‘CS’);
(1)delect from 表名 where 条件
例:删除学号为201200的学生记录
delete from student where sno=‘201200’;
(2)带子查询的删除语句IN
例:删除计算机科学系所有学生的选课记录
两个不同的表,先找在计算机科学系的学生学号,然后再将选计算机科学的学号删除
delete from sc where sno IN (select sno from student where sdept=‘CS’);
四、视图
create view 视图名(属性1,属性2)//属性可省 as 查询语句 [with check option] //可省,加上表示对视图进行插入、删除操作时要保证更新插入或删除的行满足子查询中的条件表达式
例:建立信息系学生的视图
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;
drop view 视图名 [cascade] //[cascade] 可省,表示级联删除该视图和它导出的所有视图
例:删除视图BT_S
drop view BT_S;
例:在信息系学生的视图中找出年龄小于20岁的学生
select sno,sage from IS_Student where Sage<20;
例:将信息系学生视图IS_Student 中学号为“201215” 的学生姓名改为“刘辰”;
update IS_student set sname=‘刘辰’ where sno=‘201215’;
基本概念:
(1)候选码:一个或一组属性能唯一的标识一个元组,而其子集不能
例:Student表中的学号sno
(2)主码:若有多个候选码,则选其中一个为主码
例:SC表里面学号sno和课程号cno
(3)外键,也称外码:一个表中一个(多个)属性,不是自身的主码,且这个属性和另一个表中的主码属性是同一个属性,则这个(组)属性称为外码
例:Student表中的主键是Sno,
Course表中的主码是课程号,
而Sc表中的主键是sno和课程号cno(两个组合在一起构成主码,由学号和课程号确定成绩,且这两个属性是两个不同表中的同一个属性)
Sc表中的外码是sno和cno(这两个属性是两个不同表中的同一个属性)
(1)实体完整性:主码不能重复,主码不能为空
例:学生表里面学号不能为空,且不能重复
(2)参照完整性:外键不能为空(或者均为空值)。外键等于被参照表的主码值
例:Sc表中的学号sno参照了student表中的sno(且这两个值必须相等),Sc表中的cno参照了course中的cno
(3)用户定义完整性:用户自己定义的完整性约束条件
▲可能出现考题:创建一个表,给出属性以属性的条件,定义主键和外键,而且当你更新或删除与外键有关的另一个表时,这个表是否要级联,拒绝删除、更新
(1)数据类型
①char(n):长度为n的定长字符串
②varchar(n):最大长度为n的变长字符串
③int:长整数(4字节)
④smallint:短整数(2字节)
(2)定义主键、外键
①主键:primary key(属性1,属性2)
②外键:foreign key (外键)(属性1,属性2) references 被参照表 (主键)两者属性相同
③级联更新/删除: on update/delete cascade
④拒绝更新/删除:on update/delete no action
注:一般③④跟在外键后面
(3)结构
create table 表名
(属性 数据类型[constraint] 定义的约束条件//可省(包括①非空:not null ②唯一:unique)
属性 数据类型[constraint] 定义的约束条件 ③check:自己定义的约束条件 ④定义为主码
…
primary key(属性1,属性2…)) //定义主键
foreign key(外键属性) references(参照) 被参照表(属性) on update/delete
…)
例:定义SC表中的参照完整性
create table Sc (sno char(9) not null,
cno char(4) not null,
grade smallint,
prinmary key(sno,cno),
foreign key (sno) references student(sno),
foreign key (cno) references course(cno));
外键:Sc表中的学号sno参照了student表中的sno(且这两个值必须相等),Sc表中的cno参照了course中的cno
(4)授权
grant 权限(select) on 对象类型(table,view) 对象名 to 用户 [with grant option] //可省,加上表示可以将这个权限授予其他用户
例:通过角色来实现将一组权限授予一个用户
create role R1;
使用grant语句让R1拥有student表中的select、update、insert权限
grant select ,update,insert on table student to R1;
将这个角色授予王平
grant R1 to 王平;
(5)对权限收回
revoke 权限(如select)on 对象类型(如table,view )to 用户
revoke select on table student from R1;
1.1NF:关系中的每个属性都是原子,不可再分的,每个关系都要满足1NF (平表不可嵌套)
2.2NF:满足1NF且这张表中不存在属性对主键的部分函数依赖(部分函数依赖指的是依赖于主键的一部分)
例:s(sno,sname,age,cno,grade)
主键(sno,cno) ,成绩由sno,cno共同决定
但sname,age仅由sno就可以决定,即sname,age只依赖于主键的一部分,所以不满足2NF
解决办法:“一事一地“ ,就是一张表只管一件事,拆分原表
把学生表分成学生基本信息和选课表
s(sno,sname,age)
sc(sno,cno,grade)
3.3NF:满足2NF且不存在属性对主键的传递依赖
例:Teacher(Tno ,sal_level,salary)
Tno ---->(决定)sal_level
sal_level—>(决定)salary
将2级工资水平的工资2000改为2级工资水平的工资3000,虽然工号没有变,但是工资额已经变了
老师号决定工资级别,工资级别决定工资多少,这就是典型的传递依赖
解决方案:“一事一地“
将其分为Teacher(T#,sal_level)
level(sal_level,salary)
4.BCNF:要求关系模式中,属性之间的函数依赖关系里面的决定值都必须为主键
例:邮政编码,城市,街道
城市和街道可以决定邮政编码,可以由邮政编码反过来知道城市和街道;存在这种关系就不是BCNF范式,但它是3NF范式
1.基本概念
(1)实体:□(矩形)
(2)属性:椭圆
(3)联系:◇(菱形)
2.画E-R图
3.转换为关系模型
(1)E-R图的实体转为关系(表名)
(2)E-R图的属性转换为关系的属性
(3)联系转换
①联系种类:一对一 1:1、一对多 1:n、多对一 n:1 、多对多n:m
②联系转换方法
a.1:1 两种方法
第一种:将联系转换成一个关系(表),这个关系的属性是两个关系的主码+联系的属性
第二种:将一个关系的主码+联系的属性写到另一个关系中
b.1:n 转换两种方法
第一种:将联系转换成一个关系(表),这个关系的属性是两个关系的主码+联系的属性
第二种:此时是将联系的1:n中1端关系的主码写到n端上
c.n:m
欢迎评论留言,禁止在未经允许情况下转载或抄袭。