一.引言
基本概念
二.关系模型
1.基本概念
域(Domain)
- 一组值的集合,这组值具有相同的数据类型
笛卡尔积(Cartesian Product)
- 笛卡尔积的每个元素(d1 , d2 , … , dn)称作一个n-元组(n-tuple)
- 元组的每一个值di叫做一个分量(component)
关系
- 笛卡尔积D1×D2×…×Dn的子集叫做在域D1 , D2 ,…, Dn上的关系,用R(D1 , D2 ,…, Dn )表示
- R是关系的名字,n是关系的度、目或者元
- 关系是笛卡尔积中有意义的子集
超码(super key)
- 是一个或多个属性的集合,这些属性的集合可以在一个关系中唯一地标识一个元组
候选码(Candidate Key)
- 是一个或多个属性的集合,其值能唯一标识一个元组,其任意真子集均不是超码,这样的属性集合称作候选码。
2.完整性
实体完整性:主码(主键)不为空值
空值:不知道或者无意义
数据库中所有数据类型都可以取值为null
空值不是0或者空字符串
空值的表现
参与算术运算:结果为null
参与比较运算:结果为null
参与逻辑运算:
null or true=true
null and false=false
其它情况结果为null
参照完整性:简单来说就是外码必须存在
外键可以为空,但是如果不为空,必须是对应表中存在的值
3.关系代数
选择
投影
- 投影的结果要除去重复记录(除去相同元组)
笛卡尔积
Θ连接,在笛卡尔积的基础上增加条件
从两个关系的笛卡儿积中选取给定属性间满足一定条件的元组
自然连接
- 从两个关系的笛卡儿积中选取在相同属性列B上取值相等的元组,并去掉重复的属性
注意区分自然连接和等值连接
- 自然连接会除去同名列,等值连接不会
- 当R与S无同名属性时,自然连接的结果集?R ⋈ S = R × S
- 当R与S同名属性上没有值相同的元组时,自然连接的结果集是什么?空集
并运算
- 并运算的两个关系是相容的
- 1.关系R和S必须是同元的,即它们的属性数目必须相同。 2.对任意i,R的第i个属性的域必须和S的第i个属性的域相同。
差运算
- 两个关系需要是相容的
交运算
- 两个关系需要是相容的
更名运算
除运算:给定关系R (X,Y) 和S (Y),其中X,Y为属性集合。R÷S = R中Y和S的Y相同的X
象集
除运算的代替
外连接
- 左外连接:自然连接 + 左侧关系中失配的元组
- 右外连接:自然连接 + 右侧关系中失配的元组
- 全外连接:自然连接 + 两侧关系中失配的元组
三.SQL
数据类型
注意char和varchar的区别:
char是定长的,会在字符串后面加上空格补齐长度,varchar不会,是可变长度
SQL分类
DQL: select
DML: update insert delete
DDL(Data Define): drop create alter
CREATE TABLE SC
(sno CHAR(4),
cno CHAR(4),
score SAMLLINT,
constraint pk_sc PRIMARY KEY (sno,cno),
constraint fk_scs FOREIGN KEY (sno)
REFERENCES S(sno),
constraint fk_scc FOREIGN KEY (cno)
REFERENCES C(cno),
CHECK((score IS NULL) OR
score BETWEEN 0 AND 100) )
tablespace student; //表空间
alter table T add location char(30);
alter table S MODIFY sname varchar2(30);// (注意:修改列的长度时,只能改长,不能改短)
ALTER TABLE <基本表名> DROP column <列名>[CASCADE│RESTRICT]
//此处CASCADE方式表示:在基本表中删除某列时,所有引用到该列的视图和约束也要一起自动地被删除。而RESTRICT方式表示在没有视图或约束引用该属性时,才能在基本表中删除该列,否则拒绝删除操作。
alter table 表名 drop constraint 约束名
alter table 表名 add constraint 约束名 约束类型
create [unique/distinct] [cluster] index 索引名
on 表名 (列名 [asc/desc] [ , 列名[ asc/desc]]…)
DCL: grant revoke
TCL: commit rollback
集合操作
集合并:union
集合交:intersect
集合差: except(minus)
提示
集合操作自动去除重复元组,如果要保留重复元组的话,必须用all关键词指明
union all
intersect all
except all
子查询
不相关子查询: 子查询的查询条件不依赖于父查询
子查询一定要跟在比较运算符之后
错误的例子:
SELECT sno*,sname,*dno
FROM S
WHERE ( SELECT dno
FROM S
WHERE sname = ‘ 刘晨’) = dno;
相关子查询: 子查询的查询条件依赖于父查询
- 首先取外层查询中关系的第一个元组,根据它与内层查询相关的属性值处理内层查询,若WHERE子句返回值为真,则取此元组放入结果集合中;
- 然后再取外层关系的下一个元组;
- 重复这一过程,直至外层关系全部检查完为止。
二者的区别在于:元组变量的作用域不同
我的总结
- 相关子查询一般和exists一起搭配使用
- 不相关子查询一般和in搭配使用
- 全部概念在SQL中的两种实现方式
- 示例:查询选修了全部课程的学生学号
- 法一:超集not exists (B except A)
- 法二:关系代数:÷ not in(not in)
中级SQL
外连接
SELECT s.sno,sname,gender,age,dno,cno,score
FROM s, sc
WHERE s.sno = sc.sno(*);
1.在表名后面加外连接操作符(*)或(+)指定非主体表(oracle数据库中使用(+))
2.非主体表有一“万能”的虚行,该行全部由空值组成
视图
create view view_name[(列名,列名.......)] as (子查询)
视图的属性名缺省为子查询结果中的属性名,也可以显式指明,在下列情况下,必须指明视图的所有列名:
某个目标列是聚集函数或者目标列表达式
多表连接时,选出了几个同名列作为视图的列名
需要在视图中为某个列启用新的更合适的名字
目标列是*
CREATE VIEW BT_S(sno,sname,sbirth)
AS
SELECT sno,sname,2022 - age
FROM S;
视图不会要求分配存储空间,视图中也不会包含实际的数据。
视图只保存视图定义,视图中的数据是从基表中获取。
视图中的数据在视图被引用时动态的生成。
视图的作用
定义视图能够简化用户的操作
基于多张表连接形成的视图
基于复杂嵌套查询的视图
包含导出属性的视图
视图在一定程度上提高了数据的逻辑独立性——比如S表分为两个部分,再创建一个视图和原来的S一致,就可以使原来的查询不变
注意:对视图的修改会影响原表,由于某些情况下更新视图会和原表冲突(比如视图是sno和avgscore,直接更新视图,原表怎么更新?)尽量少更新视图
了解:物化视图
事务
commit rollback
数据类型和模式
date:日期,包括年(四位)、月和日
示例:date ‘2014-3-10’
time: 时间,包括小时, 分和秒
示例:time ‘09:00:30’
timestamp: date 和 time 的组合
示例:timestamp ‘2014-3-10 09:00:30’
interval:时间段
示例:interval ‘1’ day
两个 date/time/timestamp 类型值相减产生一个interval 类型值
可以在 date/time/timestamp 类型的值上加减interval 类型的值
create index studentsno_index on s (sno)
索引是一种数据结构,用于加快查询在索引属性上取给定值的元组的速度
大对象
CLOB和BLOB,查询结果是 一个指针
高级SQL
JDBC
ER图
E是Entities实体,实体是客观存在并可相互区分的事物,可以是具体的,也可以是抽象的
R是Relationships联系
实体由属性来刻画和描述
属性分为简单属性和复合属性
也可以分为单值属性(如姓名,每一个实体在该属性上的取值唯一)和多值属性(如教师的电话号码)
还可以分为基属性和派生属性,数据库中,理论上只存基属性值,而派生属性只存其定义或依赖关系,使用时再从基属性中计算出来。但是为了提高查询效率,可以有将基属性和派生属性均保存在数据库中的现象
参与
实体集之间的关联称为参与,即实体参与联系
- 如果实体集E中的每个实体都参与到联系集R中的至少一个联系,则称E全部参与R
- 如果实体集E中只有部分实体参与到联系集R的联系中,则称E部分参与R
- 如课程和学院之间的“建设”联系,每门课都由一个学院负责建设,课程全部参与“建设”联系;但是有些学院可以不负责建设课程,学院部分参与“建设”联系。
- 用双线连接联系与完全参与的实体
角色
实体在联系中的作用称为实体的角色
由于参与联系的实体集通常是互异的,角色是隐含的一般不需要指定
当同一个实体集不止一次参与某个联系集时,为区别各实体的参与联系的方式,需要显式指明其角色
如职工与职工之间的“管理”关系,课程与课程之间的“先行”关系
弱实体
(21条消息) 彻底理解数据库ER模型(CDM)中的强实体与弱实体:追根到底_乔卿的博客-CSDN博客
一个实体的所有属性合在一起都不足以形成主码,则称这样的实体为弱实体;同一类型的弱实体形成弱实体集
反之称为强实体
弱实体需要依赖属主实体而存在,不能独立存在
弱实体集的属性不能形成主码,但不是说弱实体集就没有主码。由该弱实体集所存在依赖的强实体集的主码和该弱实体集的分辨符(部分码)共同构成的属性集合就是它的主码。
弱实体集与其拥有者之间的联系称作标识性联系(identifying relationship)
关于分辨符看这个(22条消息) 弱实体集_huxinxue的博客-CSDN博客
注意:==强实体与弱实体的联系只能是1:1或1:N。弱实体参与联系时应该是“完全参与”,因此弱实体与联系间的联系也画成双线边。==
ER模型向关系模式的转换
联系转化成的表,和实体转化成的表,可以机械地按照下述原则合并:
二元多对一联系:
联系转化的表可以和“多端” 实体转化成的表进行合并
二元一对一联系:
- 联系转化的表可以任一端实体转化成的表进行合并
- 二元一对一联系不能导致相关实体转化成的表合并
二元m:n联系:
联系转化的表和实体转化的表不能进行合并
- 多元联系:
联系转化的表和实体转化的表不能进行合并
即便是m:n:1,其转化的表和也不能进行合并
实体转化成的表,相互之间不能机械合并
联系转化成的表,相互之间不能机械合并
七.关系数据库设计
第一范式
如果某个域的元素被认为是不可再分的单元,那么这个域就是原子的(atomic)。如果一个关系模式R的所有的属性域都是原子的,我们称关系模式R属于第一范式(first normal form, 1NF)
函数依赖
简单来说就是,属性A相同,属性B就相同,称A函数决定B,记作 A→B
函数依赖可能是当前关系成立,也可能是模式上都成立
- 可分为平凡的和非平凡的
- 也可以分为全函数依赖和部分函数依赖
正则覆盖
(2条消息) 正则覆盖的求法与判断属性是否冗余_Vault Boy的博客-CSDN博客
最小覆盖
(2条消息) 关系规范化之求最小函数依赖集(最小覆盖)__TFboy的博客-CSDN博客
索引
索引文件由如下形式:searchkey 搜索码+ pointer组成
基本的索引类型:顺序索引和散列索引
顺序索引
基于搜索码值的顺序排序
主索引(primary key)
- 又称聚集索引
- 存放记录的文件按照某个搜索码指定的顺序排序,那么该搜索码对应的索引称为主索引
辅助索引(secondary index)
- 又称非聚集索引
- 用的更多,搜索码指定的顺序与文件中记录的物理顺序不同的索引
- 索引记录指向一个包含所有具有特定搜索码值的实际记录的指针的桶,辅助索引必须是稠密索引
索引顺序文件:在搜索码上有聚集索引的文件
稠密索引
- 文件中的每个搜索码都有一个索引项
- 稠密索引,主索引和辅助索引都可以用
稀疏索引
- 在稀疏索引中,只为搜索码的某些值建立索引项
- 只有索引是主索引(聚集索引)时才能使用稀疏索引 (因为包含记录的文件排序后才能根据排序顺序定位)
- 稀疏索引所占空间较小,更有可能常驻内存
- 稀疏索引定位一条记录时,通常比稠密索引更慢
索引更新
- 插入:被插入记录的搜索码值进行一次检索
- 稠密索引
- 如果搜索码值没有出现在索引中,将其插入
- 如果搜索码出现,就分为是一个指针同时指向多条记录(加一个指针)还是一个指针指向类似链表结构的多条记录(新纪录放在其他记录后面)
- 稀疏索引
- 不产生新的块不动索引
- 新块的第一个搜索码被插入到索引项中
- 稠密索引
- 删除
- 稠密索引
- 是索引中唯一记录直接删除
- 不是唯一记录,就分两种情况
- 稀疏索引
- 索引中不含待删除记录的搜索码,索引不改动
- 否则,如果待删除记录是具有该搜索码的唯一记录,用下一个记录替换;如果下一个记录有索引,则删除
- 否则,如果待删除记录不是具有该搜索码的唯一记录,用下一条记录替换
- 稠密索引
- 插入:被插入记录的搜索码值进行一次检索
多码索引
复合索引的最左匹配原则:
即最左优先,在检索数据时从复合索引的最左边开始匹配,示例:对列col1、列col2和列col3建一个复合索引,相当于建立了(col1)、(col1,col2)、(col,col2,col3)三个索引
散列索引
基于将搜索码值平均分布到若干散列桶中,一个值所属的散列桶是由一个函数决定,该函数称为散列函数
多码索引
- 覆盖索引:覆盖索引是指查询的数据列只用从索引中就能够取得,不必读取数据行,换句话说查询列要被所建的索引覆盖。一个索引包含了(或覆盖了)满足查询结果的数据就叫做覆盖索引
位图索引
实验总结
pub.student
SID | NAME | SEX | AGE | BIRTHDAY | DNAME | CLASS |
---|
pub.teacher
TID | NAME | SEX | AGE | DNAME |
---|
pub.teacher_course
CID | TID |
---|
pub.student_course
SID | CID | SCORE | TID | SCTIMR |
---|
pub.department
DAME | DID |
---|
pub.course
CID | NAME | FCID | CREDIT |
---|
实验一
create语句和insert语句格式
create注意char和varchar后面的长度要加小括号 ()
insert into 表 (字段...) values (数据)
实验二
注意子查询加括号,以及not exists/exists、minus、union的使用
实验三
REGEXP_LIKE(sid,'^[0-9]*$') 正则表达式匹配某个字段
extract(year from birthday) 从date类型的数据取出year
create table xxx as select xxx from xxx
delete from xxx where xxx
实验四
mysql中是ifnull,但是oracle是nvl
replace(class,'级','')
translate(name,'/ ','/')
实验五
to_char函数总结
(1)用作日期转换:
to_char(date,'格式');
select to_date('2005-01-01 ','yyyy-MM-dd') from dual;
select to_char(sysdate,'yyyy-MM-dd HH24:mi:ss') from dual;
(2)处理数字:
to_char(number,'格式');
select to_char(88877) from dual;
select to_char(1234567890,'099999999999999') from dual;
select to_char(12345678,'999,999,999,999') from dual;
select to_char(1234567890,'999,999,999,999.9999') from dual;
select语句查询的字段可以是另一个select语句, eg
create or replace view test5_10 as
select
cid,
(select name from pub.course where cid=a.cid) cname,
to_char(trunc(score,-1),'fm00')||'-'||to_char(trunc(score,-1)+9,'fm00') Score,
count(*) count1,
(select count(*) from pub.student_course t where a.cid=t.cid and score>=60 and score<100) count0,
round(count(*)/(select count(*) from pub.student_course where cid=a.cid and score>=60 and score<100)*100,2) percentage
from
pub.student_course a
where
score>=60 and score<=99
group by
cid, to_char(trunc(score,-1),'fm00')||'-'||to_char(trunc(score,-1)+9,'fm00')
实验六
去除重复记录
(21条消息) SQL查询去掉重复数据_sql过滤重复数据_amberom的博客-CSDN博客
group by 后面可以跟函数,eg group by substr(name,1,1)
实验七
- 索引可以多个字段联合起来建立索引
- 索引可以建立在函数上
函数trunc()
[(19条消息) SQL中TRUNC函数的用法_Schafferyy的博客-CSDN博客](https://blog.csdn.net/Schaffer_W/article/details/109046478#:~:text=TRUNC函数用于对值进行截断。. 用法有两种:TRUNC(NUMBER)表示截断数字,TRUNC(date)表示截断日期。. (1)截断数字:. 格式:TRUNC(n1%2Cn2),n1表示被截断的数字,n2表示要截断到那一位。. n2可以是负数,表示截断小数点前。. 注意,TRUNC截断不是四舍五入。. SQL> select,------------ 15. SQL> select TRUNC (15.79%2C1) from dual%3B)
1.select trunc(sysdate) from dual --2011-3-18 今天的日期为2011-3-18
2.select trunc(sysdate, 'mm') from dual --2011-3-1 返回当月第一天.
3.select trunc(sysdate,'yy') from dual --2011-1-1 返回当年第一天
4.select trunc(sysdate,'dd') from dual --2011-3-18 返回当前年月日
5.select trunc(sysdate,'yyyy') from dual --2011-1-1 返回当年第一天
6.select trunc(sysdate,'d') from dual --2011-3-13 (星期天)返回当前星期的第一天
7.select trunc(sysdate, 'hh') from dual --2011-3-18 14:00:00 当前时间为14:41
8.select trunc(sysdate, 'mi') from dual --2011-3-18 14:41:00 TRUNC()函数没有秒的精确
实验八
主要是关于事务的测试,参考我的MYSQL笔记
实验九
inseert 语句一次可以插入多行数据,并且可以加上条件筛选
insert into test9_02
select * from pub.student
where sex = '女' and sid in
(select distinct sid from pub.student_course where score < 60 )
一些SQL练习
第二次随堂练习
1.查询女生选修的全部课程名称
select cname from sc, s, c where sc.cno = s.sno and s.sex = '女' and sc.cno = c.cno;
注意在cname前加上 distinct
2.选修了数据库课程的学生的姓名和学号
select s.sno,sname from sc, s, c where sc.cno = c.cno and c.cname = '数据库' and sc.sno = s.sno;
3.选修了数据库课程或数据结构的学生的姓名和学号
select sno, sname from sc, s, c where sc.cno = c.cno and c.cname in ('数据库','数据结构') and sc.sno = s.sno;
select sno, sname from sc, s, c where sc.cno = c.cno and (c.cname = 'DS' or cname = 'DB' ) and sc.sno = s.sno;
4.数据库课程最高成绩的学生的学号
select sno,max(score) from sc where cno = (select cno from c where cname = '数据库') group by sno;
select sno
from sc
where score = (select max(score) from sc, c where sc.cno = c.cno and cname = 'DB')
and cno in (select cno from c where cname = 'DB';)
5.查询软件学院女生的人数
select count(*) from s where s.dno = (select dno from d where dname = '软件学院') and s.sex = '女';
6.平均成绩在90分以上的学生学号
select sno from (select sno,avg(score) as avgsc from sc group by sno) t where t.avgsc > 90;
标答:
select sno from sc group by sno having avg(score) > 90;
7.选修的所有课程都不及格的学生学号
select sno from sc
except
select sno from sc group by sno having score >= 60;
标答:
select sno from sc group by sno having max(score) < 60;
8.没有学生的学院名称
select dname from d where d.dno not in (select distinct dno from s);
标答:
select dname from d where d.dno not in (select distinct dno from s where dno is not null);
9.重名的学生姓名和此姓名的总人数
select sname,count(*) from s group by sname having count(*) > 2;
10.查询各个学院男女学生的平均年龄和人数(按照学院编号升序排序,按照性别降序排序)
select avg(age), count(*) from s group by dno order by dno asc,age desc;
select dno,gender, avg(age), count(*) from s where gender is not null group by dno, gender order by dno,gender desc;
11.工资最高的老师姓名及其工资数额
select tname,max(sal) from t;错了×
select tname.sal from t where sal = (select max(sal) from t);
12.选修了t1老师讲授全部课程的学生学号
这题不会
select sno from sc where
select cno from tc where tno = (select tno from t where tname = 't1')
全部的处理方式:B属于A,B - A = 空集
select sno from sc a where not exists (
(select cno from tc where tno = 't1')
minus
(select cno from sc b where a.sno = b.sno));
13.没有选修t1老师教授的课程的学生学号
select distinct sno from sc
except
select sno from sc where sc.cno in (select cno from tc where tno = (select tno from t where tname = 't1') );
select sno from s where sno not in (select sno from sc,tc where sc.cno = tc.cno and tno = 't1');
14.每个学生得到的学分数总和(不及格的不能算)
select sum(c.credit),sc.sno from sc,c where score >= 60 and sc.cno = c.cno group by sno
15.选修四门及以上课程的学生的学号和平均成绩(不及格的课程不进行统计)
select sno,avg(score) from sc where score >= 60 group by sno having count(*) >= 4;
16.查询t1老师所开课程的课程号,最高成绩,最低成绩和平均成绩。如果某门课程的成绩不全(即SCORE属性中有null)则该课程不统计
select cno,max(score), min(score), avg(score) from sc where cno in
(select cno from tc where tno = (select tno from t where tname = 't1') group by cno);
select sc.cno,max(score),min(score), avg(score) from sc,tc where sc.cno = tc.cno and tno = 't1' and
cno not in(select distinct cno from sc where score is null)
group by sc.cno;
17.查询优秀学生人数超过10人的课程编号和优秀学生人数(优秀学生:一共有三门以上课程在90分以上)
select cno from sc where sno in
(select sno from sc where score >= 90 group by sno having count(*) > 3)
group by cno having count(*) > 10;
select cno,count(*) from sc where sno in
(select sno from sc where score >= 90 group by sno having count(*) > 3)
group by cno having count(*) > 10;
18.查询学号最大的两个男生,按学号降序排列
select sno from s order by sno desc limit 2;
select
sno
from
s as a
where
gender='M' and
1 >= (select sno from s as b where gender='M' and a.sno < b.sno)
order by sno desc;
19.查询只参加一次考试就通过考试的学生
S(sno,name,gender,age,dno)
E(sno,year,month,level,score)
20.查询六级考试中合格人数最少的考试年份和月份
select
year,month,min(sum)
from
(select
year,month,count(*) as sum
from
E
where
score >= 60 and level=6
group by
year,month) t
group by
year,month
select
year,month
from
E
where
level=6 and score >= 60
group by
year,month
having count(*) <= all(select
count(*)
from
E
where
score >= 60 and level=6
group by
year,month)
第二次作业
3.9 a
select
w.ID,person_name,city
from
employee e, works w
where
e.ID = w.ID and w.company_name = 'First Bank Corporation';
b
select
w.ID,person_name,city
from
employee e, works w
where
e.ID = w.ID and w.company_name = 'First Bank Corporation' and w.salary > 10000;
c
select
e.ID
from
employee e
left join
works w
on
e.ID = w.ID
where
w.company_name <> 'Fist Bank Corporation ';
d
select
ID
from
works
where
salary > (select max(salary) from works where company_name = 'Small Bank Corporation';);
e
select
company_name
from
company a
where not exists
(select city from company where company_name = 'Small Bank Corporatin')
minus
(select city from company b where a.compoany_name = b.company_name and a.company_name <> 'Small Bank Corporatin');
//
select cname from company where city = (select city from company where cname = 'Small');
f
select
company_name,max(sump)
from (select company_name,count(*) as sump from works group by company_name);
g
select
company_name
from
(select company_name,avg(salary) as avgs from works group by company_name) t
where
t.avgs > (select company_name,avg(salary) as avgs from works group by company_name having company_name = 'First Bank Corporation');
3.10
a update employee set city = 'Newtown' where ID = '12345';
b
注意顺序问题:先给大于10000的加工资,后给小于10000的加工资
update works set salary * 1.1 where ID in (select m.manager_ID from works,manages where works.ID = manages.manager_id and works.salary < 100000);
update works set salary * 1.03 where ID in (select works.ID from works,manages where works.ID = manages.manager_id and works.salary > 100000);
3.16
a
select w.ID,e.person_name
from works w,employee e,company c
where w.ID = e.ID and w.comapny_name = c.company_name and c.city = e.city;
b
select w.ID,e.person_name
from (select w.ID,m.manager_id from works w,manages m where w.ID = m.ID) t
join employee e on t.ID = e.ID
join employee c on t.manager_id = c.ID
where e.city = c.city and e.street = c.street;
c
这题不会
select avg(salary) from works group by company_name
select w1.ID,pname
from works w1,employee e
where w1.Id = E.ID and sal > (select avg(sal) from works w2 where w1.cname = w2.cname)
d
select min(sums),company_name from (select company_name,sum(salary) as sums from works group by company_name) t;
3.17
a update works set sal * 1.1 where company_name = 'First Bank Corporation';
b update works set sal * 1.1 where company_name = 'First Bank Corporation' and ID in (select distinct manager_id from manages);
c delete from works where company_name = 'Small Bank Corporation';
3.18
employee: 主键ID,ID为int, person_name、street\city为varchar
works: 主键是ID,外键是ID和company_name,引用自employee和company表,company_name为varchar,salary为int
company: 主键company_name,类型varchar,city为varchar
manages: 主键是ID,外键是ID和manager_id,均引用自employee表
3.21
a
select memb_no,name from member m,borrowed b where m.memb_no = b.memb_no and isbn in (select isbn from books where publisher = 'McGraw-Hill');
b
select memb_no,name from member m where not exists
(select isbn from books where publisher = 'McGraw-Hill')
minus
(select isbn from borrowed b where m.memb_no = b.memb_no);
c
这题不会
select t.memb_no,t.name from (select memb_no,name from member m,borrowed b where m.mmeb_no = b.memb_no) t
where
select memb_no,name
from member
where membno in (select membno
from borrowed,books
where borrowed.isbn = books.isbn
group by publisher,membno
having count(*) >= 5);
d
select b.sum/m.sum as avgb from (select count(*) as sum from borrowed) b,(select count(*) as sum from member) m;
SELECT b.publisher, m.no, m.name
FROM book b
JOIN borrowed br ON b.isbn = br.isbn
JOIN member m ON br.no = m.no
WHERE b.publisher IN (
SELECT publisher
FROM book
GROUP BY publisher
HAVING COUNT(*) > 5
)
select sysdate from dual;
select 'ab' || 'cd' from dual;