数据库——关系演算
关系演算
以数理逻辑中的谓词演算为基础
元组关系演算语言ALPHA
由E.F.Codd提出,以数理逻辑中的谓词演算为基础语句
检索语句(查询)
GET
更新语句
PUT,HOLD,UPDATE,DELETE,DROP
一、检索操作
(1) 简单检索(即不带条件的检索)
(2) 限定的检索(即带条件的检索)
(3) 带排序的检索
(4) 带定额的检索
(5) 用元组变量的检索
(6) 用存在量词的检索
(7) 带有多个关系的表达式的检索
(8) 用全称量词的检索
(9) 用两种量词的检索
(10) 用蕴函(Implication)的检索
(1)简单检索
GET 工作空间名 (表达式)
[例1] 查询所有被选修的课程号码。
GET W (SC.Cno)
[例2] 查询所有学生的数据。
GET W (Student)
(2)限定的检索
GET 工作空间名(表达式):操作条件
[例3]查询信息系(IS) 年龄小于20岁的学号和年龄。
GET W (Student.Sno,Student.Sage): Student.Sdept='IS'∧student.Sage<20
[例 补充]查询选1号课的学生名和成绩
GET W (Student.Sname,SC.grade): SC.CNO=1 ∧ Student.Sno=SC.Sno
(3)带排序的检索
[例4] 查询计算机科学系(CS)学生的学号、年龄,结果按年龄降序排序。
GET W (Student.Sno,Student.Sage): Student.Sdept='CS' DOWN Student.Sage
排序关键字: UP升序 DOWN降序
(4)带定额的检索
[例6] 查询信息系年龄最大的三个学生的学号及其年龄,结果按年龄降序排序。
GET W (3) (Student.Sno,Student.Sage): Student.Sdept='IS' DOWN Student.Sage
(5)用元组变量的检索
元组变量: 取值在某关系内元组的量,用于形成查询条件
定义元组变量
格式: RANGE 关系名 变量名
例如:
RANGE STUDENT X
(6) 用存在量词的检索
[例8] 查询选修2号课程的学生名字。
RANGE SC X GET W (Student.Sname): 存在X (X.Sno=Student.Sno∧X.Cno=2)
查询语义:查询这样的学生名,条件是存在选课元组X,X的学号与该生的学号相等并且X的课号为2(表明该生选了2号课)
记住: 当查询条件来自工作区以外的关系时, 要使用元组变量和量词.
先定义元组变量, 在查询条件中用量词引入元组变量.
请对比下面两个查询
查询选修2号课程的学生名字。
条件来自工作区外的关系
RANGE SC X GET W (Student.Sname):存在 X(X.Sno=Student.Sno∧X.Cno=2)
查询选修2号课的学生名和成绩
条件来自工作区内的关系
GET W (Student.Sname,SC.grade): Student.Sno=SC.Sno ∧ SC.CNO=2
[例9] 查询选修了这样课程的学生学号,其先行课是6号课程。
RANGE Course CX GET W (SC.Sno): 存在 CX (CX.Cno=SC.Cno∧CX.Pcno=6)
查询CS系选修2号课程的学生名字?
RANGE SC X GET W (Student.Sname): Student.Sdept= 'CS' ∧存在 X (X.Sno=Student.Sno∧X.Cno=2)
第一个条件只用到学生表, 直接给出,第二个条件则需要元组变量和存在量词来表示了。
[例10]查询选修了先行课为6号课的课程的学生名
RANGE Course CX RANGE SC SCX GET W (Student.Sname):存在 SCX(SCX.Sno=Student.Sno ∧ 存在 CX(CX.Cno=SCX.Cno∧CX.Pcno=6))
改为前束范式形式:
RANGE Course CX RANGE SC SCX GET W (Student.Sname):存在 SCX 存在 CX (SCX.Sno=Student.Sno ∧ CX.Cno=SCX.Cno ∧ CX.Pcno=6)
(7)带有多个关系的表达式的检索
[例11] 查询成绩为90分以上的学生名与课程名。(工作区的关系,不用定义元组变量)
RANGE SC SCX GET W(Student.Sname,Course.Cname): 存在 SCX ( SCX.Sno=Student.Sno ∧ Course.Cno=SCX.Cno ∧ SCX.Grade≥90)
练习
查询CS系的学生名
GET W(STUDENT.SNAME):STUDENT.SDEPT='CS'
查询选1号课的学号,成绩
GET W(SC.SNO, SC.GRADE):SC.CNO=1
查询先行课为6的课名
GET W(COURSE.CNAME):COURSE.CPNO=6
查询选过课的学生名
RANGE SC X
GET W(Student.Sname): 存在 X (X.Sno=Student.Sno)
查询选1号课的学生名
RANGE SC X GET W(Student.Sname): 存在 X (X.Sno=Student.Sno∧X.Cno=1)
查询CS系选1号课的学生名
RANGE SC X GET W(Student.Sname): Student.Sdept='CS' ∧ 存在 X (X.Sno=Student.Sno∧X.Cno=1)
查询被选过的课名
RANGE SC X
GET W(Course.Cname): 存在 X(X.Cno=Course.Cno)
查询学号为95001学生选的课名
RANGE SC X GET W(Course.Cname):存在 X (X.Cno=Course.Cno∧X.Sno=95001)
查询CS系学生的课号,成绩
RANGE Student X GET W(SC.Cno, SC.Grade):存在 X (X.Sno=SC.Sno ∧ X.Sdept='CS')
查询选修数据库原理课的学号,成绩
RANGE Course X GET W(SC.Sno, SC.Grade):存在 X (X.Cno=SC.Cno∧X.Cname='数据库原理')
查询CS系选修数据库原理课的学生姓名
RANGE SC SCX RANGE Course CX GET W(Student.Sname): Student.Sdept='CS' ∧ 存在 SCX 存在 CX (SCX.Sno=Student.Sno ∧ CX.Cno=SCX.Cno ∧ CX.Cname='数据库原理课')
(8)用全称量词的检索
[例12] 查询不选1号课程的学生名字。查询语义:查询这样的学生,条件是对所有选课元组, 都不表明该生选了1号课(或者与该生学号不同, 或者课号不是1)
RANGE SC SCX GET W (Student.Sname): 任意 SCX ( SCX.Sno≠Student.Sno ∨ SCX.Cno≠1 )
用存在量词代替全称量词
对所有的x,P为真==不存在这样的x,P不为真
(8)不用全称量词的检索
[例12] 查询不选1号课程的学生名。
查询语义:查询这样的学生,条件是不存在选课元组,学号与该生学号相同并且课号是1 (表明该生选了1号课)
用存在量词表示:
RANGE SC SCX GET W (Student.Sname): 不存在 SCX ( SCX.Sno=Student.Sno ∧ SCX.Cno=1 )
对比使用全称量词
RANGE SC SCX GET W (Student.Sname): 任意 SCX ( SCX.Sno≠Student.Sno ∨ SCX.Cno≠1 )
练习:改为没有选。。。。?
查询选过课的学生名
RANGE SC X
GET W(Student.Sname): 存在 X (X.Sno=Student.Sno)
查询选1号课的学生名
RANGE SC X GET W(Student.Sname): 存在 X (X.Sno=Student.Sno∧X.Cno=1)
查询CS系选1号课的学生名
RANGE SC X GET W(Student.Sname): Student.Sdept='CS' ∧ 存在 X (X.Sno=Student.Sno∧X.Cno=1)
查询没有选过课的学生名
RANGE SC X
GET W(Student.Sname): 不存在 X (X.Sno=Student.Sno)
查询没有选1号课的学生名
RANGE SC X GET W(Student.Sname): 不存在 X (X.Sno=Student.Sno∧X.Cno=1)
查询CS系没有选1号课的学生名
RANGE SC X GET W(Student.Sname): Student.Sdept='CS' ∧ 不存在 X (X.Sno=Student.Sno∧X.Cno=1)
题型没有...,用不存在
(9)用两种量词的检索
[例13] 查询选修了全部课程的学生姓名。
求解思路:对于STUDENT中的一个学生,
如果对所有的课程元组CX,都存在着SC的元组SCX,表明这个学生选修了CX, 则这个学生属于查询范围。
RANGE Course CX SC SCX GET W(Student.Sname): 任意 CX 存在 SCX(SCX.Sno=Student.Sno ∧ SCX.Cno=CX.Cno)
短语:STUDENT选修了CX课
存在SCX(SCX.Sno=STUDENT.Sno ∧ SCX.Cno=CX.Cno)
存在选课元组(选课元组与STUDENT和CX有关)
(9)用存在量词代替全称量词
求解思路:查询这样的学生,条件是不存在这样的课程这个学生未选
RANGE Course CX SC SCX GET W(Student.Sname): 不存在 CX 不存在 SCX(SCX.Sno=Student.Sno ∧ SCX.Cno=CX.Cno)
短语:STUDENT选修了CX课
存在 SCX(SCX.Sno=STUDENT.Sno ∧ SCX.Cno=CX.Cno)
短语:STUDENT未选修CX课
不存在 SCX(SCX.Sno=STUDENT.Sno ∧ SCX.Cno=CX.Cno)
(10)用蕴函(Implication)的检索
[例14] 查询选修了95002学生所选课程的学生学号。
查询语义:查询这样的学生,条件是对所有课程,如果95002选了,则该学生也选修了该课
RANGE Course CX SC SCX SC SCY GET W (Student.Sno): 任意 CX( 存在 SCX (SCX.Sno=95002∧SCX.Cno=CX.Cno) =》存在 SCY(SCY.Sno=Student.Sno∧ SCY.Cno= CX.Cno))
(11)改为不用蕴函
查询语义:
对所有的课, 95002不选或者该学生选了。
RANGE Couse CX SC SCX SC SCY GET W (Student.Sno): 任意 CX( 不存在 SCX(SCX.Sno='95002'∧SCX.Cno=CX.Cno) 或者 存在 SCY(SCY.Sno=Student.Sno ∧ SCY.Cno= CX.Cno))
(12)改为不用蕴函不用全称
思路:不存在这样的课,95002选了并且这个学生未选
RANGE Couse CX SC SCX SC SCY GET W (Student.Sno): 不存在 CX(存在 SCX (SCX.Sno=95002∧SCX.Cno=CX.Cno) ∧ 不存在 SCY(SCY.Sno=Student.Sno ∧ SCY.Cno= CX.Cno))
使用离散数学的证明过程:
图书管理数据库练习
图书管理数据库有关系模式:
图书(书号,书名,价格,作者)
读者(读者号,姓名,性别,年龄)
借阅(读者号,书号,借日期,还日期,罚款金额)
用元组关系演算查询:
1 查询价格大于50的书名和作者名
2 查询(一次)罚款金额>20元的读者名
3 查询被年龄大于60的读者借过的书名和作者名
4 查询看了所有书的读者名
5 查看了2001号读者所看过的所有书的读者号
6 查询没有借过书的读者姓名
1 查询价格大于50的书名和作者名
GET W(图书.书名, 图书.作者): 图书.价格>50
关系代数?
π 书名,作者名(σ 价格>50(图书))
2 查询(一次)罚款金额>20元的读者名
查询语义:查询这样的读者,条件是存在借阅元组表明该读者的罚款金额>20)
RANGE 借阅 借阅X GET W(读者.姓名): 存在 借阅X (借阅X.读者号=读者.读者号 并且 借阅X.罚款金额>20)
关系代数?
π 姓名(σ 罚款金额>20(借阅 连接 读者))
3 查询被年龄大于60的读者借过的书名和作者名
查询语义:查询这样的图书,条件是存在借阅元组和读者元组,表明该图书被年龄大于60的读者借过
RANGE 读者 读者X RANGE 借阅 借阅X GET W(图书.书名, 图书.作者): 存在 借阅X 存在 读者X (借阅X.图书号=图书.图书号 并且 借阅X.读者号=读者X.读者号 并且 读者X.年龄>60)
关系代数?
π 作者,书名 (σ 年龄者>60 (读者 连接 借阅 连接 图书 ))
4 查询看了所有书的读者名
(用不存在量词)
查询语义:查询这样的读者,条件是不存在这样的图书,该读者未看
RANGE 图书 图书X
借阅 借阅X
GET W(读者.姓名): 不存在 图书X (不存在 借阅X(借阅X.读者号=读者.读者号 并且 借阅X.图书号=图书X.图书号 ) )
关系代数?
π 姓名(( π 读者号,书号(借阅) ÷ π 书号(图书)) 连接 读者
5 查看了2001号读者所看过的所有书的读者名
查询语义: 查询这样的读者姓名,条件是对所有的图书, 如果存在借阅X 元组表明2001号读者借, 则存在借阅Y元组表明该读者也借
RANGE 图书 图书X RANGE 借阅 借阅X RANGE 借阅 借阅Y GET W(读者.姓名): 任意 图书X(存在 借阅X(借阅X.图书号=图书X.图书号 并且 借阅X.读者号=‘2001’ ) =》
存在 借阅Y(借阅Y.读者号=读者.读者号 并且 借阅Y.图书号=图书X.图书号 ))
上题不用全称和蕴涵实现
查询语义: 查询这样的读者姓名,条件是不存在这样的图书, 2001借并且该读者不借(存在借阅X 元组表明2001号读者借并且不存在借阅Y元组表明该读者借)
RANGE 图书 图书X RANGE 借阅 借阅X RANGE 借阅 借阅Y GET W(读者.姓名): 不存在 图书X(存在 借阅X(借阅X.图书号=图书X.图书号 并且 借阅X.读者号=‘2001’ )
不存在 借阅Y(借阅Y.读者号=读者.读者号 并且 借阅Y.图书号=图书X.图书号 ))
关系代数?
π 读者号,书号(借阅) ÷ π书号(σ 读者号=2001 (读者 连接 借阅))
6 查询没有借过书的读者姓名
解题思路: 查询读者名, 条件是不存在这样的借阅X,借阅X的读者号与该读者的读者号相等
GET W(读者.姓名): 不存在 借阅X(借阅X.读者号=读者.读者号)
关系代数?
π姓名( ( π读者号 (读者) - π读者号 (借阅)) 连接 读者)
工程供应数据库练习
供应商-零件-工程-供应数据库关系模式
S(SNO,SNAME,STATUS,CITY);
P(PNO,PNAME,COLOR,WEIGHT);
J(JNO,JNAME,CITY);
SPJ(SNO,PNO,JNO,QTY);
(1) 求供应工程J1的供应商号
关系代数:
投影 SNO(选择 JNO=‘J1’(SPJ))
关系演算:
GET W (SPJ.SNO):SPJ.JNO=‘J1’
2) 求供应工程J1零件P1的供应商号
关系代数:
投影 SNO(选择 JNO=‘J1’ 并且 PNO=‘P1’(SPJ))
关系演算:
GET W (SPJ.SNO):SPJ.JNO=‘J1’ 并且 SPJ.PNO=‘P1’
(3) 求供应工程J1零件为红色的供应商号SNO
关系代数:
GET W (SPJ.SNO):SPJ.JNO=‘J1’并且 SPJ.PNO=‘P1’
关系演算:
RANGE P PX
GET W(SPJ.SNO): SPJ.JNO=‘J1’ 并且 存在 PX(PX.PNO=SPJ.PNO 并且 PX.COLOR=‘红’)
(4) 求没有使用天津供应商生产的红色零件的工程号JNO
关系代数:
投影 JNO(J)-投影 JNO(选择 CITY=‘天津’ 并且 COLOR=‘红’(S 连接 SPJ 连接 P))
关系演算:
从J中查询这样的JNO, 条件是不存在这样的供应元组SPJX表明该工程使用了天津生产的红色零件
GET W(J.JNO): 不存在 SPJX( SPJX.JNO=J.JNO ∧ 存在 SX(SX.SNO=SPJX.SNO∧ SX.CITY=‘天津’) ∧ 存在 PX(PX.PNO=SPJX.PNO ∧ PX.COLOR=‘红’))
(5) 求至少用了供应商S1供应的所有零件的工程号JNO
关系代数:
投影 JNO,PNO(SPJ) 除 投影 PNO (选择 SNO=‘S1’(SPJ))
从J中查询这样的工程号,条件是: 不存在这样的零件元组PX, S1供应而该工程不用
GET W(J.JNO): 不存在 PX( 存在 SPJX(SPJX.PNO=PX.PNO ∧ SPJX.SNO=‘S1’) ∧ 不存在 SPJY(SPJY.PNO=PX.PNO ∧ SPJY.JNO=J.JNO ))
(6) 查询使用了全部零件的工程号JNO
关系代数:
投影JNO,PNO(SPJ) 除 投影 PNO (SPJ)
关系演算:
从J中查询这样的工程号,条件是:不存在这样的零件元组PX, 该工程不用
GET W(J.JNO): 不存在 PX( 不存在 SPJY(SPJY.PNO=PX.PNO ∧ SPJY.JNO=J.JNO ))