2025真题:
【说明】
某银行数据库系统的部分数据库关系模式如下:
支行:BRANCH(Bno,Bname, address),各属性分别表示支行编号、名称、地址;
客户:CUSTOMER(CID,Cname, tel)各属性分别表示客户编号、姓名、电话;
贷款:LOAN (Lno, Bno, CID, amount, Ldatetime),各属性分别表示贷款编号、支行编号、客户编号、
贷款金额、贷款时间;
还款:PAYMENT(Pno,Lno,num,Pdatetme),各属性分别表示还款编号、贷款编号、还款金额、还款时间。
有关关系模式的说明如下:
(1)实下划线标出的属性是表的主键。
(2)每位客户只存储一个电话号码。
(3)每位客户在同一个支行可以有多笔贷款。
(4)每笔贷款可以分多次还清,即每笔贷款可以有多条还款记录。每次的还款金额最少为100。
(5)贷款时间和还款时间不能为空。
根据以上描述,将SOL语句的空缺部分补充完整
1. (4分)假设其它表已经创建,请将下面创建还款表PAYMENT的SQL语句补充完整,要求定义实体完整性约束、参照完整性约束,以及其他完整性约束。
CREATE TABLE PAYMENT(
Pno CHAR(6)(a),
Lno CHAR(5) (b),
num DECIMAL(10,2) (c),
Pdatetime DATETIME(d) )a:PRIMARY KEY
b:references LOAN(Lno)
c:CHECK(num>=100)
d:NOT NULL
2.(3分)在贷款表LOAN中新增一条记录,各属性值依次为:L0005,B010,C0008,12000,getdatetime(),其中getdatetime()为获取当前系统时间的函数。此功能可以由下面的SQL语句实现,请补全。(e)_LOAN_(f)_('L0005,'B010,C0008,12000, (g) );
e:insert into
f:values
g:getdatetime()
3. (4分)查询在’A支行‘有贷款的所有客户的姓名和电话。此功能由下面的SQL语句实现,请补全。
SELECT Cname,tel
FROM LOAN,CUSTOMER,(h)
(i) LOAN.CID=CUSTOMER.CID
AND __(j)__
AND__(k)__注意要用上题目提供的提示条件,首先可以确定Bname=‘A支行’
其次发现三表两两连接缺少了连接符号
h:BRANCH
i:WHERE
j:LOAN.Bno=BRANCH.Bno # k 和 j 答案顺序无要求可以颠倒
k:Bname=‘A支行’
4. (4分)查询在该银行贷款总金额超过10万元的客户姓名、电话以及他们各自的贷款总金额。某大语言模型提供了实现该查询功能的SQL语句如下所示。此语句存在3个错误,其中1个错误由例子给出并改正,请找出其余2个错误并改正。
SELECT Cname As 客户姓名,tel As 电话号码,SUM(amount) As 贷款总金额
FROM LOAN,CUSTOMER
WHERE LOAN.CID=CUSTOMER.CID
GROUP BY CID HAVING amount>100000;例:
错误:SELECT子句的Cname 改正:MIN(Cname)
错误:SELECT子句的tel 改正:MIN(tel)
错误:HAVING子句的amount 改正:SUM(amount)
高频考点:SELECT中的非聚合列,必须出现在GROUP BY中。
这里用CID group by,那么上面的select必须全部是聚合的。
(为什么不是GROUP BY CNAME?因为客户的姓名可能重名,其次,group by后面并不一定是要select中出现,因为select实际上是最后去选要显示哪些列,只要在from里面就可以了)
这里取MIN是什么意思?我们只按CID分组之后,一行里面只有一个聚合了的amount,但是有好多重复的姓名和电话,这里强行只取其中一个,强行变成聚合列。用MAX也是可以的。
我们还可以
SELECT
Cname AS 客户姓名,
tel AS 电话号码,
SUM(amount) AS 贷款总金额
FROM LOAN, CUSTOMER
WHERE LOAN.CID = CUSTOMER.CID
GROUP BY CID, Cname, tel
HAVING SUM(amount) > 100000;HAVING SUM(amount) > 100000;
首先,我们要判断的是总金额。其次,amount既然不在group里面,我们不可以用处理分组的HAVING去处理它。
1.
【说明】
某教务管理系统的部分数据库关系模式如下:
学生:STUDENT(Sno,Sname,Ssex,Sage,Sdept),各属性分别表示学号、姓名、性别、年龄、所在系名;
课程:COURSE(Cno,Cname,Cpno,Ceredit),各属性分别表示课程号、课程名、选修课的课程号、学分;
选课:SC(Sno,Cno,Grade),各属性分别表示学号、课程号、成绩。
有关关系模式的说明如下:
(1)下划线标出的属性是表的主键。
(2)课程名取值唯一。
根据以上描述,回答下列问题,将SQL语句的空缺部分补充完整。
完整性约束/参照性约束
【问题1】(3分)
请将下面创建课程表COURSE的SQL语句补充完整,要求定义实体完整性约束、参照完整性约束以及其他完整性约束。
CREATE TABLE COURSE(
Cno CHAR(4)PRIMARY KEY,
Cname CHAR(30) (a),
Cpno CHAR(4) REFERENCES (b) ((c))
Ccredit INT);课程:COURSE(Cno,Cname,Cpno,Ceredit)
实体完整性:保证表中的每一行数据是唯一的,已由主键(Primary Key)实现
参照完整性:保证表间关系正确,外键值必须在主表存在或为 NULL。
Cname是课程名,题目提到课程名唯一,因此Cname加上UNIQUE
Cpno 是外键,它参照的是同一个表 COURSE 的主键 Cno。
因此(b) COURSE (c) Cno
【问题2】(4分)
有一门课程号为“C036的新开课要求所有学生选修。该课的基本信息已经录入课程表COURSE中,现需在选课表SC中插入该课的选课记录。实现此功能的SQL语句如下,请补全。
(d) INTO SC(Sno, (e))
SELECT Sno, (f)
FROM (g );选课:SC(Sno,Cno,Grade) 学号、课程号、成绩
插入语法:
INSERT INTO 表名(列1, 列2) SELECT 列1, 列2[或常量] FROM 源表
插入选课记录,d填写INSERT
这道题只操作其中的两列,选课和成绩无关,另一列应当是课程号
e填写Cno
(f)处填入'C036'是因为该SQL语句需要为所有学生插入固定课程号" C036"的选课记录。此处'C036'是常量值,直接指定课程号,并非从STUDENT表中读取。
学号的信息只能是从学生表中来,因此G填写STUDENT
JOIN连接查询
【问题3】(4分)
查询每一门课程的间接选修(选修课的选修课),要求输出课程号和间接选修课的课程号。即使某门课程没有选修课,也需要输出,不过其间接选修课为空。此功能由下面的SQL语句实现,请补全。
SELECT K1.Cno, (h)
FROM COURSE K1 (i) OUTER JOIN COURSE K2 (j) ((k));从两个COURSE表的别名K1,K2中连接查询,在select处首先要选择两张表。K1.Cno是某个课程号,K2我们需要某个课程号的选修课程号Cpno。
(h) K2.Cpno
连接查询的语法:FROM 主表 [连接方式] JOIN 被关联表 ON 条件
(i) LEFT (j) ON
K1取的是选修课的课程号,K2取的是选修课的选修课的课程号,题目已经写出以K1为主表,即使某门课程没有选修课,也需要输出,那么就是以保留左边的左连接。
假如有A/B两张表,我们FROM A RIGHT JOIN B,和FROM B LEFT JOIN A,这两种写法在查询结果上是完全等价的。
判断连接条件:K1的选修课的课程号,就是K2他自己的课程号
K1.Cpno = K2.Cno
注意不要写反了变成k1.cno=k2.Cpno,那就反过来K2的选修课是K1了
嵌套查询/where not exist
【问题4】(4分)
查询选修了课程表中已有全部课程的学生,要求输出学号和姓名。此功能由下面的SQL语句实现,请补全。
SELECT Sno,Sname FROM STUDENT
WHERE NOT EXISTS
(SELECT * FROM (l)
WHERE (m)
(SELECT * FROM (n)
WHERE(o) ));答案:
我要找的学生:
↓
不存在这样一门课:
这门课,这个学生没有选SELECT Sno, Sname FROM STUDENT
WHERE NOT EXISTS ( #3.找不到任何一门课这学生没选,则成立select学生
SELECT * FROM COURSE
WHERE NOT EXISTS ( #2.找不到的时候,not exists成立,筛出了没选的课
SELECT * FROM SC #1.最内层查询:找出所有【有人选的课】
WHERE SC.Cno = COURSE.Cno
AND SC.Sno = STUDENT.Sno
)
);
结构:select * from 某主表 where not exist(某嵌套查询)
遍历主表的每一行,并对当前主表的行执行嵌套查询,嵌套查询的内容
找不到 → 真 → 保留;找得到 → 假 → 丢弃
最内层:SELECT * FROM SC WHERE SC.Cno = 所有课程中的某个 AND SC.Sno = 所有学生中的某个
选课:SC(Sno,Cno,Grade)
课程号Sno匹配课程表COURSE,学号Cno匹配学生表STUDENT
把某个课程有某个学生选了的所有记录都找出来了
当最内层这个select,通过外层给它的SC.Cno和SC.Sno查不到,不成立的时候,说明某个课没有学生选,NOT EXISTS成真,这个没人选的COURSE被保存下来。SELECT * FROM COURSE
SELECT Sno, Sname FROM STUDENT WHERE NOT EXISTS ( 遍历了所有的课程,如果任何一门课都找不到没选的,条件成立,把这个学生筛选出来 )
2.
【说明】
某工程项目管理系统的部分数据库关系模式如下:
项目:PROJECT(Jno,Jname,City,Date ),各属性分别表示项目代码、项目名称、项目所在城市和项目开始日期;
零件:PART (Pno,Pname,Color,Sno,Stock),各属性分别表示零件代码、零件名称、零件颜色、零件所在仓库代码及库存量;
供应情况:PJ(Pno,Jno,Qty ),各属性分别表示零件代码、项目代码、使用量;
仓库:STORE(Sno,Sname,Address ),各属性分别表示仓库代码、仓库名称、仓库地址。
有关上述关系模式的说明如下:
(1)下划线标出的属性是表的主键。
(2)零件表的属性Sno参照了仓库表的主码。一种零件只存放在一个仓库,库存量最低为0。
(3)供应情况表的属性Pno和Jno分别参照了零件表和项目表的主码。
根据以上描述,回答下列问题,将SQL语句的空缺部分补充完整。
【问题1】(4分)
请将下面创建零件表PART的SQL语句补充完整,要求定义实体完整性约束、参照完整性约束,以及其他完整性约束。
CREATE (a) PART(
Pno CHAR(10) (b)
Pname CHAR(20),
Color CHAR(4),
Sno CHAR(4) REFERENCES (c) (Sno)
Stock INT (d) );零件:PART (Pno,Pname,Color,Sno,Stock)
零件表的属性Sno参照了仓库表的主码。一种零件只存放在一个仓库,库存量最低为0。
(a) TABLE:SQL 创建表的完整关键字为 CREATE TABLE。
(b) PRIMARY KEY:Pno 是零件表的主键,需定义实体完整性约束。
(c) STORE:Sno 是外键,参照仓库表的主码 Sno,因此写表名 STORE。
用户定义完整性约束
(d) CHECK(Stock >= 0):题目规定“库存量最低为0”,需用 CHECK 约束限制 Stock 的取值范围。
列名 数据类型 [可选 CONSTRAINT 约束名] CHECK (列名 条件表达式)
视图
视图定义从 CREATE VIEW 名称 AS ... 开始,到第一个分号结束。后续要使用直接以后直接 SELECT * FROM 视图。
【问题2】(3分)
创建视图PARTUSED,给出在项目中已使用零件的代码和使用量。此视图的创建语句如下,请补全。CREATE VIEW PARTUSED AS SELECT Pno, (e) AS Usage FROM PJ (f) BY (g);
供应情况:PJ(Pno,Jno,Qty ),各属性分别表示零件代码、项目代码、使用量;在供应情况表 PJ 中,同一种零件可能被多个不同的项目使用,所以它的使用量 Qty 是分散在多行记录中的。
Pno (零件代码)Jno (项目代码)Qty (使用量)
P01 J01 10
P01 J02 15
P02 J01 8(e) SUM(Qty):需要统计每个零件的总使用量,因此对 Qty 求和,并用别名 Usage 表示。
(f) GROUP:看到select末尾有 BY 要联想到组成 GROUP BY 子句。
(g) Pno:
题目说给出在项目中已使用零件的代码和使用量,如果分组,应该是按零件代码分组,统计出每种零件在所有项目中的使用总量。
【问题3】(4分)
在视图PARTUSED的基础上,查询所有零件的信息要求输出每种零件的零件代码、零件名、零件颜色和零件总量(使用量与库存量之和 ),查询结果按照零件总量降序排列。此功能由下面的SQL语句实现,请补全。
SELECT Pno,Pname, Color, (h) AS Total
FROM PART,PART_USED
WHERE PART.Pno=PART_USED.Pno
(i)
SELECT Pno,Pname,Color,Stock AS Total
FROM PART
WHERE Pno (j)
( SELECT DISTINCT Pno FROM PJ )
ORDER BY Total (k)零件:PART (Pno,Pname,Color,Sno,Stock),各属性分别表示零件代码、零件名称、零件颜色、零件所在仓库代码及库存量;
(h)要表示使用量与库存量之和 ,但是注意这里不会是聚合函数,因为SQL中的聚合函数都是针对某列的多个行计算。而这里是将选出的单独两值进行相加。都是数值类型直接相加即可。
(h) PART_USED.Usage + PART.Stock
(k) DESC:ORDER BY Total DESC 表示按零件总量降序排列。
UNION/DISTINCT
把多个查询结果上下堆叠成一张表,UNION 是纵向连接(行与行拼接),JOIN 是横向连接(列与列拼接)。
对比题目发现,上下两端查询的列,列数/含义和数据类型完全一致。应当使用UNION。
为什么?我们在视图PART_USED中只定义了查询使用过的零件。为了补上丢失的“未使用零件”,需要:找出那些 Pno 在 PART 表中存在,但不在 PJ 表中的零件。
SELECT DISTINCT Pno FROM PJ;
将Pno列的元素去重地选出,每个只出现一次
WHERE Pno NOT IN (SELECT DISTINCT Pno FROM PJ)
选出的零件都是之前没在PJ中出现过的
转移表记录
【问题4】(4分)
由于某种原因,要拆除代码为'A006'的仓库,该仓库中的零件转入'A002'仓库存放。据此更新数据库的功能由下面的SQL语句实现,请补全。
UPDATE (l) SET (m) WHERE Sno='A006';
(n) FROM (o) WHERE Sno='A006'仓库:STORE(Sno,Sname,Address ),各属性分别表示仓库代码、仓库名称、仓库地址。
零件:PART (Pno,Pname,Color,Sno,Stock),各属性分别表示零件代码、零件名称、零件颜色、零件所在仓库代码及库存量;
UPDATE PART SET Sno = 'A002' WHERE Sno = 'A006';
DELETE FROM STORE WHERE Sno = 'A006';(l) PART:要转移零件,需修改零件所在的仓库代码,更新的是 PART 表。
(m) Sno = 'A002':将零件的仓库代码从 'A006' 改为 'A002'。
看到分号,第一个sql语句已经结束。下一步还是A006?那只能是删除原来的了。
(n) DELETE:拆除仓库意味着从仓库表中删除该仓库记录。
(o) STORE:删除的是 STORE 表中 Sno = 'A006' 的仓库记录。
3.
【说明】
某订单管理系统的部分数据库关系模式如下:
客户:CUSTOMERS(Cno, Cname, Cage, Csex),各属性分别表示客户编号、客户姓名、年龄和性别;
商品:GOODS(Gno, Gname, Gprice, Gorigin),各属性分别表示商品编号、商品名称、单价和产地;
订单:ORDERS(Ono, Cno, Gno, Oprice, Onumber),各属性分别表示订单编号、客户编号、商品编号、顾客购买商品的单价和数量。
有关关系模式的说明如下:
(1)下划线标出的属性是表的主键。
(2)商品表中的Gprice是商品的当前价格,可能会发生变动;订单表中的Oprice是订单成交时的商品单价。
(3)一个订单只包含一位顾客购买的一种商品;其商品数量至少1件,最多99件。
根据以上描述,回答下列问题,将SQL语句的空缺部分补充完整。
【问题1】(3分)
请将下面创建订单表的SQL语句补充完整,要求定义实体完整性约束、参照完整性约束,以及其他完整性约束。
CREATE TABLE ORDERS (
Ono CHAR(20) PRIMARY KEY,
Cno CHAR(10) (a),
Gno CHAR(15) (b),
Oprice NUMERIC(7,2),
Onumber SMALLINT (c) );订单:ORDERS(Ono, Cno, Gno, Oprice, Onumber),各属性分别表示订单编号、客户编号、商品编号、顾客购买商品的单价和数量。
注意观察!Cno和Gno都是其他表的主键,且题目要求定义参照完整性约束
references customers(Cno)
references goods(Gno)
对于大于且小于的商品数量,使用AND符合连接
CHECK(Onumber >= 1 AND Onumber <= 99)
【问题2】(5分)
查询所有订单的详细情况,要求输出订单号(Ono)、 客户姓名(Cname)、 商品名称(Gname)、单价(Oprice)、数量(Onumber)和金额(Oamount), 查询结果按照金额从大到小排列。此功能由下面的SQL语句实现,请补全。
SELECT Ono, Cname, Gname, Oprice, Onumber,(d) AS Oamount
FROM CUSTOMERS, ORDERS, GOODS
WHERE (e)
AND (f)
(g) BY (h) ;(d) Oprice * Onumber:订单金额 = 单价 × 数量,又取了别名 Oamount。
这里要注意到这次的select选择了三张表,后续子句Where...and应当是三张表两两连接。
(e) ORDERS.Cno = CUSTOMERS.Cno:关联订单表和客户表。
(f) ORDERS.Gno = GOODS.Gno:关联订单表和商品表。((e)和(f)顺序可互换)
(g) ORDER:排序子句关键字。
写排序的时候不要忘了,还需要BY 排序列名
(h) Oamount DESC:按金额从大到小(降序)排列。
【问题3】(5分)
创建已售商品信息视图,给出已售商品的编号(Gno)、名称(Gname)、订单个数(Onum)及平均每单的商品数量(GAnum)。此视图的创建语句如下,请补全。
CREATE (i ) GOODS_SOLD AS
SELECT ORDERS. Gno AS Gno, MIN (GOODS. Gname) AS Gname,
(j) AS Onum, (k) AS GAnum .
FROM ORDERS, GOODS
WHERE ORDERS.Gno = GOODS . Gno .
(l ) BY_ (m);注意题目,创建的是视图而表!!
(i) VIEW:创建视图的关键字。
COUNT/AVG聚合函数
(j) COUNT(*):统计每种商品的订单个数(每个订单只包含一种商品,所以计算订单表的行数即可)。
(k) AVG(Onumber):计算该商品平均每单的购买数量。
(l) GROUP:又考察了一次视图末尾分组。因为同时select了聚合和非聚合列。
(m) ORDERS.Gno:按商品编号分组。这里要注意需求是商品信息,编号是唯一的主键。按名称会导致信息丢失。
EXCEPT
它把两个查询结果当成完整的集合,然后进行差集运算。这要求上下两个查询的列数和数据类型必须一致。
A EXCEPT B = 在 A 中存在,但在 B 中不存在的记录
B EXCEPT A = 在 B 中存在,但在 A 中不存在的记录【问题4】(2分)
查询未售出商品的编号和名称。此功能由下面的SQL语句实现,请补全。
SELECT Gno, Gname
FROM (n)
(o)
SELECT Gno , Gname
FROM GOODS_SOLD;
(n) GOODS:从商品表中选取所有商品的编号和名称。
(o) EXCEPT:用集合差操作,减去已售出商品视图 GOODS_SOLD 中存在的商品,剩下的就是未售出商品。EXCEPT 会自动去重。
4.
【说明】
某竞赛管理系统的部分数据库关系模式如下:
选手: PLAYER(PnO, Phame, Sex, Region, Tel),各属性分别表示参赛选手的编号、姓名、性别、地区和联系电话;
竞赛项目: CONTEST(CnO, Chame, Type, Date),各属性分别表示竞赛项目的编号、名称、类别和举办日期;
选手参赛: PC(Pno, Cno, City, Rank, Point),各属性分别表示选手编号、竞赛项目编号、竞赛所在城市、选手取得的名次和积分。
有关关系模式的说明如下:
(1)下划线标出的属性是表的主码。
(2)选手参赛表的属性Pno和Cno分别参照了选手表和竞赛项目表的主码。
(3)一个选手参加一项竞赛有一个名次和一个积分,名次有4个取值('一','二','三','无' )。另外,竞赛所在城市不能为空。
根据以上描述,回答下列问题,将SQL语句的空缺部分补充完整。
用户自定义完整性约束
【问题1】 (5分)
请将下面创建选手参赛表PC的SQL语句补充完整,要求定义实体完整性约束、参照完整性约束,以及其他完整性约束。
CREATE TABLE PC(
Pno CHAR(10) REFERENCES(a)(Pno),
Cno CHAR(3) REFERENCES(b)(Cno),
City CHAR(20)(c),
Rank CHAR(20)(d)
Point SMALLINT,
(e);选手参赛: PC(Pno, Cno, City, Rank, Point),各属性分别表示选手编号、竞赛项目编号、竞赛所在城市、选手取得的名次和积分。
(a) PLAYER:Pno 参照选手表的主码 Pno。
(b) CONTEST:Cno 参照竞赛项目表的主码 Cno。
(c) NOT NULL:题目明确“竞赛所在城市不能为空”。
(d) CHECK(Rank IN ('一','二','三','无')):名次只有4个取值,用 CHECK 约束限制。
多个主键的实体完整性约束
主题题目要求定义实体完整性约束,在列声明中还没有定义主键
(e) PRIMARY KEY(Pno, Cno):由选手编号和竞赛项目编号联合作为主键。
【问题2】(6分)
查询所有未参加“Al”类别竞赛的选手,要求输出选手的编号(Pno),查询结果按照选手编号的升序排列。此功能由下面的SQL语句实现,请补全。
SELECT Pno FROM (f)
WHERE Pno (g) (
SELECT (h) FROM PC, Contest
WHERE (i)
(j) Type='Al' )
(k) Pon;既然查询的结果是选手,输出的是选手编号,那么最外层select的就是选手表。填写PLAYER
k处,末尾要按照选手编号升序,必然是Order by
选手: PLAYER(PnO, Phame, Sex, Region, Tel)
竞赛项目: CONTEST(CnO, Chame, Type, Date),各属性分别表示竞赛项目的编号、名称、类别和举办日期;
选手参赛: PC(Pno, Cno, City, Rank, Point),各属性分别表示选手编号、竞赛项目编号、竞赛所在城市、选手取得的名次和积分。
内层联合了PC和CONTEST两表查询,where子句应当是等值条件
(h) PC.Pno:子查询返回参加Al类别竞赛的选手编号集合。
(i) PC.Cno = Contest.Cno:关联选手参赛表和竞赛项目表,确保比赛项目匹配。
(j) AND:连接条件,同时限定竞赛类别为'Al'。
(g)内层查询找出了参加AI类别竞赛的选手,外层筛选使用 NOT IN 进行排除
外键约束下的删除顺序
【问题3】(4分)
由于某种原因,编号为“E06”的竞赛项目在正式举办前被取消了。而此前系统中已经记录了一些选手的报名参赛情况,因此需要在系统中删除“E06”的竞赛项目记录,以及该竞赛的所有报名参赛纪录。根据问题1在选手参赛表PC上定义的参照完整性约束,此功能可以由下面的SQL语句实现,请补全。
(l) FROM (m) WHERE Cno= 'E06';
(n) FROM (o) WHERE Cno= 'E06';
竞赛项目: CONTEST(CnO, Chame, Type, Date),各属性分别表示竞赛项目的编号、名称、类别和举办日期;
选手参赛: PC(Pno, Cno, City, Rank, Point),各属性分别表示选手编号、竞赛项目编号、竞赛所在城市、选手取得的名次和积分。
(l) DELETE:删除操作的关键字。
(m) PC:先删除选手参赛表PC中相关报名记录,以解除外键约束。
(n) DELETE:删除操作的关键字。
(o) CONTEST:再删除竞赛项目表CONTEST中的项目记录。
PC表有外键参照CONTEST表,必须先删除子表(PC)中相关记录,才能成功删除父表(CONTEST)中的记录,否则会违反参照完整性约束。
5.
【说明】
某学生信息管理系统的部分数据库关系模式如下:
学生:Student ( stuno, stuname, stuage, stusex, schno),各属性分别表示学生的学号、姓名、年龄、性别,以及学生所属学院的编号;--- stuno 主键
学院:School ( schno, schname, schstunum ),各属性分别表示学院的编号、名称及学生人数;--- schno 主键
俱乐部:Club (clubno,clubname, clubyear, clubloc ),各属性分别表示俱乐部的编号、名称、成立年份和活动地点; --- clubno 主键
参加:JoinClub ( stuno, clubno. joinyear ),各属性分别表示学号、俱乐部编号,以及学生加入俱乐部 的年份。 --- stuno, clubno 主键
有关关系模式的说明如下:
(1) 学生的性别取值为‘F’和‘M’ (F表示女性,M表示男性)。
(2) 删除一个学院的记录时,通过外键约束级联删除该学院的所有学生记录。
(3) 学院表中的学生人数与学生表中的实际人数要完全保持一致。也就是说,当学生表中增减记录时,就要自动修改相应学院的人数。
根据以上描述,回答下列问题,将SQL语句的空缺部分补充完整。
级联删除CASCADE
【问题1】(4分)
请将下面创建学生表的SQL语句补充完整,要求定义实体完整性约束、参照完整性 约束,以及其他完整性约束。
CREATE TABLE Student (
stuno CHAR(11) ( a ),
stuname VARCHAR,
stuage SMALLINT,
stusex CHAR(1) ( b),
schno CHAR(3) ( c) ON DELETE ( d));a) PRIMARY KEY:定义实体完整性,学号为主键。
(b) CHECK(stusex IN ('F','M')):用户定义完整性,限制性别只能取'F'或'M'。
(c) REFERENCES School(schno):参照完整性,学院编号外键参照学院表的主键。
(d) CASCADE:级联删除,当删除学院记录时,自动删除该学院所有学生。
视图
当视图的 SELECT 语句中,每一列都有一个明确的、无冲突的名字时,数据库可以自动推断列名,就可以不写括号。
当多表连接导致出现同名列,或者想重新给列命名时(相当于AS),就需要写括号
【问题2】(5分)
创建俱乐部人数视图,能统计每个俱乐部已加入学生的人数,属性有clubno> clubname 和clubstunum。对于暂时没有学生参加的俱乐部,其人数为0。此视图的创建语句如下, 请补全。
CREATE VIEW CS_NUMBER ( clubno, clubname, clubstunum ) AS
SELECT JoinClub.clubno, ( e ) , ( f )
FROM JoinClub, Club
WHERE JoinClub.clubno = Club.clubno
( g ) BY JoinClub.clubno (h )
SELECT clubno, clubname, 0 FROM Club
WHERE clubno NOT IN
(SELECT DISTINCT clubno FROM ( i));参加:JoinClub ( stuno, clubno. joinyear ),各属性分别表示学号、俱乐部编号,以及学生加入俱乐部 的年份。
俱乐部:Club (clubno,clubname, clubyear, clubloc ),各属性分别表示俱乐部的编号、名称、成立年份和活动地点
(e) Club.clubname:输出俱乐部名称,因为clubno是主键,clubname函数依赖于它,可直接使用。注意其他列都附带表名的时候,也应该写club.,哪怕单独写clubname并不会报错
select一个有着group的count
(f) COUNT(*):题目要求统计每个俱乐部已加入学生的人数。算有多少行要联想到。
【实际执行的顺序是】
第1步:FROM + WHERE(做笛卡尔积,再过滤)
↓
第2步:GROUP BY(按 clubno 分组)
↓
第3步:SELECT(计算 COUNT(*),输出结果)
lubno clubname COUNT(*)
C01 篮球社 3(组C01有3行)
C02 足球社 2(组C02有2行)这里的COUNT最后数的是每组的人数,然后其值作为表的一列。
一般不COUNT(列),因为可能漏掉空值行,而且性能较差!
......
WHERE JoinClub.clubno = Club.clubno
( g ) BY JoinClub.clubno (h )
SELECT clubno, clubname, 0 FROM Club
WHERE clubno NOT IN
(SELECT DISTINCT clubno FROM ( i));(g) GROUP:有按俱乐部编号分组统计。有聚合和非聚合函数就得group by
(h) UNION:将两部分结果合并:上半部分select是有学生的俱乐部统计人数,下半部分是无学生的俱乐部SELECT clubno, clubname, 0 FROM Club 给那些没有学生参加的俱乐部手动补上一个人数为 0 的记录。
注意:WHERE clubno NOT IN
(i) JoinClub:子查询找出已有学生参加的俱乐部编号,然后排除就得到了没学生的。
触发器
【问题3】(4分)
每当系统中新加或删除一个学生,就需要自动修改相应学院的人数,以便保持系统中学生人数的完整性与一致性。此功能由下面的触发器实现,请补全。
CREATE TRIGGER STU_NUM_TRG
AFTER INSERT OR DELETE ON ( j )
REFERENCING new row AS nrow, old row AS orow FOR EACH(k )
BEGIN
IF INSERTING THEN
UPDATE School ( l )
END IF;
IF DELETING THEN
UPDATE School ( m);
END IF;
END;(j) Student:触发器是针对学生表上的插入或删除操作触发的。
(k) ROW:因为需要引用每一行被插入或删除的数据(nrow 和 orow),所以必须是行级触发器。
REFERENCING new row AS nrow, old row AS orow FOR EACH ROW
REFERENCING 子句就是给 NEW 和 OLD 这两个系统默认的行引用,换成你自定义的别名 nrow 和 orow。
有些数据库之间使用NEW和OLD直接引用新、旧行,有些必须REFERENCING 子句显式地给新、旧行定义别名
(l) 插入学生时,将该学生所属学院的学生人数加 1,条件用新插入行的学院编号 nrow.schno。
SET schstunum=schstunum+1 where School.schno= nrow.schno
WHERE schno = nrow.schno 的作用是把更新范围精确锁定到“该学生所属的那一个学院”,确保只改一条记录。不加 WHERE 会把所有学院的人数都改掉,造成数据混乱。
(m) 删除学生时,将该学生所属学院的学生人数减 1,条件用被删除行的学院编号 orow.schno。
SET schstunum=schstunum-1 where School.schno=orow.schno
补充。这里是SET,不是为变量赋值,所以是普通等号,不是:=
【问题4】(2分)
查询年龄小于19岁的学生的学号、姓名及所属学院名,要求输出结果把同一个学院的学生排在一起。此功能由下面的SQL语句实现,请补全。
SELECT stuno, stuname, schname FROM Student, School WHERE Student.schno = School.schno
AND stuage <19 ( n ) BY ( o);
(n)order
(o)schname学院:School ( schno, schname, schstunum ),各属性分别表示学院的编号、名称及学生人数;
6.
【说明】
某公司要对其投放的自动售货机建立商品管理系统,其数据库的部分关系模式如下:
售货机:VEM(VEMno,Location),各属性分别表示售货机编号、部署地点;
商品:GOODS(Gno,Brand,Price),各属性分别表示商品编号、品牌名和价格;
销售单:SALES(Sno,VEMno,Gno,SDate,STime),各属性分别表示销售号、售货机编号、商品编号、日期和时间;
缺货单:OOS(VEMno,Gno,SDate,STime),各属性分别表示售货机编号、商品编号、日期和时间。
相关关系模式的属性及说明如下:
(1)售货机摆放固定种类的商品,售货机内每种商品最多可以储存10件。管理员在每天结束的时候将售货机中所有售出商品补全。
(2)每售出一件商品,就自动向销售单中添加一条销售记录。如果一天内某个售货机上某种商品的销售记录达到10条,则表明该售货机上该商品已售完,需要通知系统立即补货,通过自动向缺货单中添加一条缺货记录来实现。
根据以上描述,回答下列问题,将SQL语句的空缺部分补充完整。
【问题 1】 (3 分)
请将下面创建销售单表的 SQL 语句补充完整,要求指定关系的主码和外码约束。
CREATE TABLE SALES(
Sno CHAR(8) (a)
VEMno CHAR(5) (b)
Gno CHAR(8) (c)
SDate DATE,
STime TIME);销售单:SALES(Sno,VEMno,Gno,SDate,STime)
(a) PRIMARY KEY:定义实体完整性,销售号为主键。
(b) REFERENCES VEM(VEMno):定义外键约束,售货机编号参照售货机表的主键。
(c) REFERENCES GOODS(Gno):定义外键约束,商品编号参照商品表的主键。
分析Group by
【问题 2】 (4分)
创建销售记录详单视图 SALES_Detail ,要求按日期统计每个售货机上各种商品的销售数量,属性有 VEMno、Location 、Gno、Brand 、Price 、amount 和 SDate。为方便实现,首先建立一个视图 SALES_Total ,然后利用SALES_Total 完成视图 SALES_Detail 的定义。
CREATE VIEW SALES_Total(VEMno,Gno,SDate,amount) AS
SELECT VENno ,Gno ,SDate ,count(*)
FROM SALES
GROUP BY (d);
CREATE VIWE (e) AS
SELECT VEM.VEMno, Location, GOODS.Gno, Brand, Price, amount, SDate
FROM VEM, GOODS, SALESTotal
WHERE (f) AND (g)要求按日期统计每个售货机上各种商品的销售数量
售货机VEM(VEMno,Location),售货机编号、部署地点;
商品GOODS(Gno,Brand,Price),商品编号、品牌名和价格;
销售单SALES(Sno,VEMno,Gno,SDate,STime),销售号、售货机编号、商品编号、日期和时间;
第一个视图创建了总量amount供第二个视图使用、由于有group by,实际上count数的数量是分组后每组的数量并成为一列
(d) VEMno, Gno, SDate:按售货机、商品和日期分组,才能统计每天每台机器每种商品的销售数量。在出现了聚合列的情况下,剩下的非聚合列必须填到group by里面!
(e) SALES_Detail:创建第二个视图的名称。先创建了total视图,后面就是利用total创建detail视图
看到select from三个表,那么where子句肯定是三个表的两两等值连接
(f) VEM.VEMno = SALES_Total.VEMno:连接售货机表,获取地点信息。
(g) GOODS.Gno = SALES_Total.Gno:连接商品表,获取品牌和价格。
触发器
【问题 3】 (3分)
每售出一件商品,就自动向销售单中添加一条销售记录。如果一天内某个售货机上某种商品的销售记录达到 10 条,则自动向缺货单中添加一条缺货记录。需要用触发器来实现缺货单的自动维护。程序中的 GetTime()获取当前时间。
CREATE(h) OOS_TRG AFTER (i) ON SALES
REFERENCING new row AS nrow
FOR EACH ROW
BEGIN
INSERT INTO OOS
SELECT SALES .VENno, (j) GetTime ()
FROM SALES
WHERE SALES.VEMno = nrow.VEMno AND SALES.Gno = nrow.Gno AND SALES.SDate = nrow.SDate
GROUP BY SALES.VEMno, SALES.Gno, SALES.SDate
HAVING count (*) > 0 AND mod(count (*), 10)=0;
END(h) 填:TRIGGER
i:当销售单中插入新记录时,我们需要检查销量并可能向缺货单插入记录。因此触发事件是 INSERT
缺货单:OOS(VEMno,Gno,SDate,STime)
OOS为全码表,必须四个属性标识唯一的一行,INSERT语句必须插入所有列的值(一般考试都是插入全部列),因此:
(j)处应该为:SALES.Gno, SALES.Sdate
WHERE SALES.VEMno = nrow.VEMno AND SALES.Gno = nrow.Gno AND SALES.SDate = nrow.SDate
从 SALES 表中筛选与新插入行属于同一售货机、同一商品、同一天的销售记录。
HAVING count(*) > 0 AND mod(count(*), 10) = 0
该组内的销售记录数大于 0 且为 10 的整数倍时,触发插入操作。即每售出 10 件商品,自动生成一条缺货通知。mod就是是取模/求余数,计算被除数 ÷ 除数 的余数。
找最多用HAVING COUNT(*) >= ALL
【问题 4】 (3分)
查询当天销售最多的商品编号、品牌和数量。程序中的 GetDate()获取当天日期。
SELECT GOODS.Gno, Brand, (k)
FROM GOODS,SALES
WHERE GOODS.Gno=SALES.GNO AND SDATE =GetDate()
GROUP BY (i)
HAVING(m) (SELECT count(*)
FROM SALELS
WHERE SDATE = GetDate()
GROUP BY Gno);(k) COUNT(*):统计当天每种商品的销售数量。
(l) GOODS.Gno, Brand:按商品编号和品牌分组,因为 SELECT 中出现了这两列非聚合函数,必须全部出现在 GROUP BY 中。
一条完整的 SQL 查询,执行顺序是这样的:
FROM:找到数据表,进行表连接(JOIN)。
WHERE:对原始数据进行行级过滤。
GROUP BY:将过滤后的数据按指定列进行分组。
HAVING:对分组后的数据进行组级过滤。
SELECT:从过滤后的小组里,抽取或计算要显示的列。
ORDER BY:对最终的输出结果进行排序。(m) COUNT(*) >= ALL:
内层的SELECT count(*) FROM SALELS WHERE SDATE = GetDate() GROUP BY Gno之前已经接触过,select一个分组的count就是:数每组的个数,然后其值作为表的一列。也就是今天每个商品卖了几件。
where用来过滤行数据,having(条件表达式)过滤组数据,只保留 COUNT(*) >= ALL的组。
HAVING COUNT(*) >= ALL ( SELECT COUNT(*) ......
内层的count是当天每种商品各卖了几个,是单纯的数字列,比如3、5、4......,然后ALL(子句)就是外层的count要比他们中任意一个都要大于或等于。
外层的count就是某个商品编号和品牌构成的组,当天的销量。
【问题5】 (2分)
查询一件都没有售出的所有商品编号和品牌。
SELECT Gno ,Brand
FROM GOODS
WHERE GNO(N)
SELECT DISTINCT GNO
FROM(o);
(N) NOT IN:筛选未售出商品,即商品编号不在已售出商品列表中的商品。
(o) SALES:从销售单表中获取所有售出过的商品编号。
排除法where not in/not exist的区别
NOT IN 和 NOT EXISTS 无法在不改变语句结构的情况下直接等价替换。它们注定会导致子句的写法不同。外面有列是NOT IN,外面没有列是NOT EXIST
子查询没有引用外层列 → 用 IN / NOT IN。
要判断的列表里不可以有NULL
WHERE GNO (N) (SELECT DISTINCT GNO FROM (o))这里子查询独立返回一列(商品编号列表),不与外层主查询的行进行关联。
子查询引用了外层列(关联子查询) → 用 EXISTS / NOT EXISTS。
NOT EXISTS 是关联判断,子查询中只要关联条件不成立,EXISTS 就为 FALSE,不受 NULL 值干扰。
WHERE NOT EXISTS (
SELECT 1 FROM SALES
WHERE SALES.Gno = GOODS.Gno
)7.
【说明】
某单位公用车辆后勤服务部门数据库的部分关系模式如下:
驾驶员:EMP(Eno,Ename, Age, Sex, telephone),各属性分别表示驾驶员工号、姓名、年龄、性别和电话号码;
车辆:CAR(Cno,Brand,Capacity),各属性分别表示汽车车牌号、品牌名和排量;
调度:SCHEDULE(Sno,Eno,Cno,StartTime, Endtime),各属性分别表示调度号、驾驶员工号、汽车车牌号、发车时间和收车时间。
奖金:BONUS(Eno,Year,Month,Amount),各属性分别表示驾驶员工号、年、月和当月的奖金数量。
有关车辆调度的相关说明如下:
公用车的行驶时间只能在工作时间内,因此规定调度表中每天安排发车的时间在上午07:00:00至下午18:00:00范围内。
【问题1】(4分)
请将下面创建调度关系的SQL语句的空缺部分补充完整,要求指定关系的主码、外码,以及调度表中每天安排发车的时间在上午07:00:00至下午18:00:00范围内的约束(由函数Time Get_time(DATETIME StartTime)返回出车的时间)。
CREATE TABLE SCHEDULE(
Sno CHAR(10),
Eno CHAR(10) (a) ,
Cno CHAR(8) (b) ,
StartTime DATETIME (c) ,
EndTime DATETIME,
PRIMARY KEY (d) );调度:SCHEDULE(Sno,Eno,Cno,StartTime, Endtime),调度号、驾驶员工号、汽车车牌号、发车时间和收车时间。
(a) REFERENCES EMP(Eno):Eno 是外键,参照驾驶员表的主码。
(b) REFERENCES CAR(Cno):Cno 是外键,参照车辆表的主码。
(c) CHECK(Get_time(StartTime) BETWEEN '07:00:00' AND '18:00:00'):用户定义完整性约束,限制发车时间在上午7点到下午6点范围内。看到区间范围就
(d) Sno:调度号 Sno 为主键,唯一标识一次调度。
【问题2】(6分)
(1)创建所有'奥迪'品牌汽车的调度信息的视图AudiSCHEDULE,属性有Eno、Ename、Cno、Brand、StartTime和EndTime,请将下面SQL语句的空缺部分补充完整。
CREATE (e)
AS
SELECT EMP,Eno,Ename, CAR,Cno,Brand, StartTime, EndTime
FROM EMP,CAR, SCHEDULE
WHERE (f) 驾驶员:EMP(Eno,Ename, Age, Sex, telephone),驾驶员工号、姓名、年龄、性别和电话号码;
车辆:CAR(Cno,Brand,Capacity),汽车车牌号、品牌名和排量;
调度:SCHEDULE(Sno,Eno,Cno,StartTime, Endtime),调度号、驾驶员工号、汽车车牌号、发车时间和收车时间。
(e) VIEW AudiSCHEDULE:创建视图的语法关键字,指定视图名称。
(f) EMP.Eno = SCHEDULE.Eno AND
CAR.Cno = SCHEDULE.Cno AND
CAR.Brand = '奥迪':三表连接条件,同时筛选出奥迪品牌车辆
这里要注意,除了两两连接之外,题目还要限定车辆品牌
触发器
(2)驾驶员的奖金在收车时间写入时,由出车时间段自动计算,并用触发器来实现奖金的自动维护,函数float Bonus_value(DATETIME StartTime, DATETIME EndTime)依据发车时间和收车时间来计算本次出车的奖金。系统在每月初自动增加一条该员工的当月奖金记录,初始金额为零。请将下面SQL语句的空缺部分补充完整。
CREATE (g) Bonus_TRG AFTER (h) ON SCHEDULE
REFERENCING new row AS nrow
FOR EACH ROW
BEGIN
UPDATE BONUS
SET (i)
WHERE (j) AND Year=Get_Year(nrow.StartTime)
AND Month= Get_Month(nrow.StartTime) ;
END奖金:BONUS(Eno,Year,Month,Amount),驾驶员工号、年、月和当月的奖金数量。
(g) TRIGGER:创建触发器的关键字。
(h) UPDATE:触发器事件,在收车时间写入(即更新调度记录)时触发。
Bonus_value(DATETIME StartTime, DATETIME EndTime)依据发车时间和收车时间来计算本次出车的奖金。
触发器定义在 SCHEDULE 表上,奖金的计算根据发车时间和收车时间的NEW新插入行计算
(i) Amount = Amount + Bonus_value(nrow.StartTime, nrow.EndTime):累加本次出车的奖金,使用系统函数根据出车/收车时间计算。
(j) BONUS.Eno = nrow.Eno:关联条件,定位到特定驾驶员当月的奖金记录。
选取最多用HAVING COUNT
【问题3】(5分)
请将下面SQL语句的空缺部分补充完整。
(1)查询调度次数最多的汽车车牌号及其品牌。
SELECT CAR. Cno, Brand
FROM CAR, SCHEDULE
WHERE CAR.Cno =SCHEDULE.Cno
GROUP BY (k)
HAVING (l) (SELECT COUNT(*)
FROM SCHEDULE
CROUP BY Cno);(k) CAR.Cno, Brand:SELECT 中出现了 CAR.Cno 和 Brand,均为非聚合列,必须全部出现在 GROUP BY 中。
只要使用了 GROUP BY,SELECT 中出现的所有非聚合列必须全部出现在 GROUP BY 子句中
(l) COUNT(*)>= ALL:子查询返回每辆车的调度次数集合,COUNT(*) >= ALL 表示当前车的调度次数大于等于所有车的次数,即最大值。如果多辆车并列,会全部输出。找最多的题就联系到Group+having count组合
排除法用NOT IN
(2)查询所有在调度表中没有安排过“大金龙”品牌车辆的驾驶员工号和姓名。
SELECT Eno, Ename
FROM EMP
WHERE Eno (m) (
SELECT Eno
FROM (n)
WHERE (o)
AND brand=‘大金龙');驾驶员:EMP(Eno,Ename, Age, Sex, telephone),驾驶员工号、姓名、年龄、性别和电话号码;
车辆:CAR(Cno,Brand,Capacity),汽车车牌号、品牌名和排量;
调度:SCHEDULE(Sno,Eno,Cno,StartTime, Endtime),调度号、驾驶员工号、汽车车牌号、发车时间和收车时间。
(m) NOT IN:筛选“不在”已安排大金龙车辆的驾驶员集合中。
这里where后面跟着一个列,肯定不是WHERE NOT EXIST
(n) SCHEDULE, CAR:子查询需要连接调度表和车辆表才能获取品牌信息。
(o) SCHEDULE.Cno = CAR.Cno:两表连接条件,确保车辆匹配。
8.
【说明】
某大型集团公司的数据库的部分关系模式如下:
员工表:EMP( Eno,Ename,Age,Sex,Title),各属性分别表示员工工号、姓名、年龄、性别和职称级别,其中性别取值为“男”“女”;
公司表:COMPANY( Cno,Cname,City),各属性分别表示公司编号、名称和所在城市;
工作表:WORKS( Eno,Cno,Salary),各属性分别表示职工工号、工作的公司编号和工资。
有关关系模式的属性及相关说明如下:
(1)允许一个员工在多家公司工作,使用身份证号作为工号值。
(2)工资不能低于1500元。
根据以上描述,回答下列问题:
【问题1】(4分)
请将下面创建工作关系的SQL语句的空缺部分补充完整,要求指定关系的主码、外码,以及工资不能低于1500元的约束。
CREATE TABLE WORKS(
Eno CHAR(10) (a) ,
Cno CHAR(4) (b) ,
Salary int (c) ,
PRIMARY KEY (d) ,
);工作表:WORKS( Eno,Cno,Salary),职工工号、工作的公司编号和工资
(a) REFERENCES EMP(Eno):定义外键约束,参照员工表的主键。因为题目已经说明此列是主键之一,所有不可能是UNIQUE
(b) REFERENCES COMPANY(Cno):定义外键约束,参照公司表的主键。
(c) CHECK(Salary >= 1500):用户定义完整性约束,保证工资不低于1500元。
(d) Eno, Cno:主键的题目一定要小心主键属性是不是只有一个
多表连接+限定条件
【问题2】(6分)
(1)创建女员工信息的视图FemaleEMP,属性有Eno、Ename、Cno、Cname和Salary,请将下面SQL语句的空缺部分补充完整。
CREATE (e)
AS
SELECT EMP.Eno,Ename,COMPANY.Cno,Cname,Salary
FROM EMP, COMPANY, WORKS
WHERE (f) ;员工表:EMP( Eno,Ename,Age,Sex,Title),员工工号、姓名、年龄、性别和职称级别,其中性别取值为“男”“女”;
公司表:COMPANY( Cno,Cname,City),公司编号、名称和所在城市;
工作表:WORKS( Eno,Cno,Salary),职工工号、工作的公司编号和工资。
(e) VIEW FemaleEMP:创建视图的语法关键字及视图名称。
(f) EMP.Eno = WORKS.Eno AND
COMPANY.Cno = WORKS.Cno AND
EMP.Sex = '女':三表连接条件,之后不要忘记加上题目的条件!!!并筛选出女员工。
(2)员工的工资由职称级别的修改自动调整,需要用触发器来实现员工工资的自动维护,函数float Salary_value(char(10) Eno)依据员工号计算员工新的工资。请将下面SQL语句的空缺部分补充完整。
CREATE (g) Salary_TRG AFTER (h) ON EMP
REFERENCING new row AS nrow
FOR EACH ROW
BEGIN
UPDATE WORKS
SET (i)
WHERE (j) ;
END(g) TRIGGER:创建触发器的关键字。
(h) UPDATE:触发事件为更新员工表(职称级别修改即 UPDATE 操作)。
(i) Salary = Salary_value(nrow.Eno):使用函数根据新员工号计算并设置新工资。
(j) WORKS.Eno = nrow.Eno:关联条件,UPDATE的是哪行?是和新插入的那行一样的行
【问题3】(5分)
请将下面SQL语句的空缺部分补充完整。
(1)查询员工最多的公司编号和公司名称。
SELECT COMPANY.Cno,Cname
FROM COMPANY,WORKS
WHERE COMPANY.Cno= WORKS.Cno
GROUP BY (k)
HAVING (l) ( SELECT COUNT(*)
FROM WORKS
GROUP BY Cno
);(k) COMPANY.Cno, Cname:SELECT 中的两个非聚合列都必须出现在 GROUP BY 中。
(l) COUNT(*) >= ALL:子查询返回每个公司的员工数集合,当前组的员工数大于等于所有值即为最大值。
(2)查询所有不在“中国银行北京分行”工作的员工工号和姓名。
SELECT Eno,Ename
FROM EMP
WHERE Eno (m) (
SELECT Eno
FROM (n)
WHERE (o)
AND Cname=‘中国银行北京分行’
);FROM是Eno在的表,要连接的是Cname在的表
(m) NOT IN:外层列 Eno 紧接子查询,用 NOT IN 排除在目标公司工作的员工。
(n) WORKS, COMPANY:Eno在Work里,Cname在COMPANY里
(o) WORKS.Cno = COMPANY.Cno:两表连接条件。