数据库经常用到的增删改查语句如下(主要为查询),根据《数据库系统概论》书籍整理,少许修改。其中最重要的是聚集函数的使用(经常与group by一起使用),也是面试中经常问到的。文中有相关的查询语句与例句,表结构与表中的数据如下,可以直接用来在数据库中建表,本人使用的是MySQL数据库。
亲测全部OK^_^^_^ 在这个举国欢庆的日子里,祝福祖国母亲生日快乐!
使用的三张表:
1.学生表(字段:学生学号Sno,姓名Sname,性别Ssex,年龄Sage,所在的系:Sdept)
2.课程表(字段:课程号Cno,课程名称Cname,前导课程号Cpno,学分:Ccredit) ,前导课程即为学习这门课程之前需要学习的课程。
3.学生成绩表(字段:学生学号Sno,课程号Cno,成绩Grade)
表结构和数据如下:
SET NAMES utf8;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for `student`
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`Sno` char(9) COLLATE utf8_bin NOT NULL,
`Sname` char(20) COLLATE utf8_bin NOT NULL,
`Ssex` char(6) COLLATE utf8_bin DEFAULT NULL,
`Sage` smallint(3) DEFAULT NULL,
`Sdept` char(20) COLLATE utf8_bin DEFAULT NULL,
PRIMARY KEY (`Sno`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
-- ----------------------------
-- Records of `student`
-- ----------------------------
BEGIN;
INSERT INTO `student` VALUES ('2016001', 'Anmy', 'Female', '20', 'CS'), ('2016002', 'Jack', 'Male', '21', 'Sale'), ('2016003', 'Pavan', 'Male', '22', 'CS'), ('2016004', 'Emma', 'Female', '21', 'MA'), ('2016005', 'Alan', 'Male', '19', 'IS'), ('2016006', 'June', 'Female', '20', 'IS'), ('2016007', 'Apple', 'Male', '21', 'MA');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
SET NAMES utf8;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for `studentcourse`
-- ----------------------------
DROP TABLE IF EXISTS `studentcourse`;
CREATE TABLE `studentcourse` (
`Sno` char(9) NOT NULL,
`Cno` char(4) NOT NULL,
`Grade` smallint(10) DEFAULT NULL,
PRIMARY KEY (`Sno`,`Cno`),
KEY `student_id` (`Sno`),
KEY `course_id` (`Cno`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of `studentcourse`
-- ----------------------------
BEGIN;
INSERT INTO `studentcourse` VALUES ('2016001', '1', '99'), ('2016001', '2', '95'), ('2016001', '3', '89'), ('2016001', '7', '95'), ('2016001', '8', '92'), ('2016002', '1', '90'), ('2016002', '2', '92'), ('2016002', '3', '95'), ('2016002', '6', '94'), ('2016002', '8', '90'), ('2016003', '1', '90'), ('2016003', '2', '89'), ('2016003', '3', '98'), ('2016003', '7', '92'), ('2016003', '8', '91'), ('2016004', '1', '95'), ('2016004', '3', '92'), ('2016004', '5', '89'), ('2016004', '7', '91'), ('2016004', '8', '98'), ('2016005', '2', '90'), ('2016005', '3', '92'), ('2016005', '5', '91'), ('2016005', '6', '93'), ('2016005', '8', '90'), ('2016006', '1', '92'), ('2016006', '2', '89'), ('2016006', '4', '95'), ('2016006', '7', '0'), ('2016006', '8', '94'), ('2016007', '2', '90'), ('2016007', '8', '0');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
SET NAMES utf8;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for `course`
-- ----------------------------
DROP TABLE IF EXISTS `course`;
CREATE TABLE `course` (
`Cno` char(4) COLLATE utf8_bin NOT NULL,
`Cname` char(40) COLLATE utf8_bin NOT NULL,
`Cpno` char(4) COLLATE utf8_bin DEFAULT NULL,
`Ccredit` smallint(2) DEFAULT NULL,
PRIMARY KEY (`Cno`),
KEY `Cpno` (`Cpno`),
KEY `Cpno_2` (`Cpno`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
-- ----------------------------
-- Records of `course`
-- ----------------------------
BEGIN;
INSERT INTO `course` VALUES ('1', '数据结构', '2', '6'), ('2', '计算机网络', '8', '6'), ('3', '操作系统', '8', '6'), ('4', '数据库', '1', '6'), ('5', '羽毛球', '', '2'), ('6', '英语', '', '5'), ('7', '国学鉴赏', '', '2'), ('8', '计算机基础', null, '4');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
相关语句如下:
1.-- 查询全体学生的姓名及其出生年份
SELECT
Sname,
2018 - Sage
FROM
student;
SELECT
Sname,
'Year of Birth:',
2018 - Sage,
LOWER(Sdept)
FROM
student;
2.-- 指定别名来改变查询结果的列标题
SELECT
Sname NAME,
'Year of Birth:' BIRTH,
2018 - Sage BIRTHYEAR,
LOWER(Sdept) DEPARTMENT
FROM
student;
3.-- DISTINCT消除重复的行
Select DISTINCT(Sno) from studentcourse;
4.-- 查询计算机科学系全体学生的名单
Select Sname from student where Sdept = 'CS';
5.-- between...and../not between ... and .../in或not in--属于或不属于指定的集合元组
select Sname from student where Sdept in ('CS','Sale');
-- 等价于
select Sname from student where Sdept='CS' or Sdept='Sale';
6.-- ORDER BY子句对查询结果按照一个或多个属性列的升序或降序排列,缺省值为升序
select Sno,Grade from studentcourse where Cno='3' order by Grade desc;
/* 聚集函数:count([DISTINCT|ALL] *)统计元组个数;count([DISTINCT|ALL] <列名>)统计一列中值的个数
sum([DISTINCT|ALL] <列名>)计算一列值的总和(此列必须为数值型);avg([DISTINCT|ALL] <列名>)计算一列值的平均值(此列必须为数值型);
max([DISTINCT|ALL] <列名>)求一列值的最大值;min([DISTINCT|ALL] <列名>)求一列值的最小值;*/
7.-- 查询学生总人数
select count(*) from student;
8.-- 查询选修了课程的学生人数
select count(Distinct Sno) from studentcourse;
9.-- 计算1号课程的学生平均成绩
select avg(grade) from studentcourse where Cno='1';
10.-- 查询选修1号课程的学生最高分数
select max(grade) from studentcourse where Cno='1';
11.-- 查询学生2016001选修课程的总学分数
select sum(c.Ccredit) from studentcourse sc, course c where sc.Sno='2016001' and sc.Cno=c.Cno;
12.-- 在聚集函数遇到空值时,除count(*)外,都跳过空值而只处理非空值
Group by子句将查询结果按某一列或多列的值分组,值相等的为一组,对查询结果分组的目的是为了细化聚集函数的作用对象。
如果未对查询结果分组,聚集函数将作用于整个查询结果。
13.-- 求各个课程号及相应的选课人数
select Cno,count(Sno) from studentcourse group by Cno; -- 该语句对查询结果按Cno值分组,所有具有相同Cno值的元组为一组,然后对每一组作用聚集函数count计算,以求得该组的学生人数。
14.-- 使用having短语指定筛选条件
-- 查询选修了3门以上课程的学生学号
select Sno from studentcourse group by Sno having count(*) > 3;
/* 用group by子句按Sno进行分组,再用聚集函数count对每一组计数。having短语给出了选择组的条件,只有满足条件的组才会被选出来。
where子句作用于基本表或视图,从中选择满足条件的元组。Having短语作用于组,从中选择满足条件的组。*/
15.-- 自身连接
-- 查询每一门课的间接先修课(即先修课的先修课)
-- 在course表中,只有每门课的直接先修课信息,而没有先修课的先修课。要找到这个信息,必须先对一门课找到其先修课,再按此先修课的课程号,查找它的先修课程。需要course表与其自身连接
select first.Cno, second.Cpno from course first, course second where first.Cpno = second.Cno;
16.-- 外连接:把舍弃的元组也保存在结果关系中,而在其他属性上填空值(Null). 左外连接,右外连接,复合条件连接
select student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade from student left join studentcourse on student.Sno = studentcourse.Sno;
17.-- 嵌套查询:查询选择了2号课程的所有学生名单
SELECT /*外层查询或父查询*/
Sname
FROM
student
WHERE
Sno IN (
SELECT /*内层查询或子查询*/
Sno
FROM
studentcourse
WHERE
Cno = '2'
)
-- 子查询的select语句中不能使用order by子句,order by子句只能对最终查询结果排序
18.-- 带有in谓词的子查询:查询与“Anmy”在同一个系学习的学生
/*Step by step:
Step 1.确定“Anmy”所在的系
select Sdept from student where Sname='Anmy';
查询结果为 CS
Step 2.查找所有在CS系学习的学生
select Sno,Sname,Sdept from student where Sdept='CS';
将第一步查询嵌入到第二部查询条件中,如下:
*/
SELECT
Sno,
Sname,
Sdept
FROM
student
WHERE
Sdept IN (
SELECT
Sdept
FROM
student
WHERE
Sname = 'Anmy'
);
-- 解法二:自身连接
SELECT
s1.Sno,
s1.Sname,
s1.Sdept
FROM
student s1,
student s2
WHERE
s1.Sdept = s2.Sdept
AND s2.Sname = 'Anmy';
-- 解法三:用exist
SELECT
Sno,
Sname,
Sdept
FROM
student s1
WHERE
EXISTS (
SELECT
*
FROM
student s2
WHERE
s2.Sdept = s1.Sdept
AND s2.Sname = 'Anmy'
);
19.-- 找出每个学生超过他选修课程平均成绩的课程号和成绩
SELECT
Sno,
Cno,
Grade
FROM
studentcourse sc1
WHERE
sc1.Grade >= (
SELECT
avg(sc2.Grade)
FROM
studentcourse sc2
WHERE
sc2.Sno = sc1.Sno
);
20.-- 带有ANY或ALL谓词的子查询
-- 查询其他系中比计算机系某一学生年龄小的学生姓名和年龄
SELECT
Sname,
Sage,
Sdept
FROM
student
WHERE
Sage < ANY (
SELECT
Sage
FROM
student
WHERE
Sdept = 'CS'
)
AND Sdept <> 'CS';
-- 解法二:用聚集函数来实现。首先用子查询找出CS系中最大年龄(22),然后在父查询中查所有非CS系且年龄小于22岁的学生。
SELECT
Sname,
Sage,
Sdept
FROM
student
WHERE
Sage < (
SELECT
max(Sage)
FROM
student
WHERE
Sdept = 'CS'
)
AND Sdept <> 'CS';
21.-- 查询其他系中比计算机科学系所有学生年龄都小的学生姓名及年龄
SELECT
Sname,
Sage
FROM
student
WHERE
Sage < (
SELECT
min(Sage)
FROM
student
WHERE
Sdept = 'CS'
)
AND Sdept <> 'CS';
-- 用聚集函数实现子查询通常比直接用ANY或ALL查询效率要高。
22.-- 带有exist谓词的子查询
-- 查询所有选修了1号课程的学生姓名
解法1:select s.Sname from student s,course c,studentcourse sc where s.Sno = sc.Sno and sc.Cno=c.Cno and c.Cno=1;
解法2:select Sname from student where exists (select * from studentcourse where Sno=student.Sno and Cno=1);
/*集合查询:SELECT语句的查询结果是元组的集合,所以多个SELECT语句的结果可进行集合操作。集合操作主要包括UNION,交操作INTERSECT和差操作EXCEPT(MySql不支持INTERSECT和EXCEPT).
注意,参加集合操作的各查询结果的列数必须相同;对应项的数据类型也必须相同*/
23.-- 查询计算机科学系的学生及年龄不大于20岁的学生(UNION),如果要保留重复元组则用UNION ALL
select * from student where Sdept='CS' UNION select * from student where Sage<=20;
24.-- 查询计算机科学系的学生与年龄不大于20岁的学生
select * from student where Sdept='CS' and Sage<=20;
25.-- 查询同时选修了课程1和2的学生
SELECT
sc.Sno,
s.Sname
FROM
studentcourse sc,
student s
WHERE
s.Sno = sc.Sno
AND sc.Cno = 1
AND sc.Sno IN (
SELECT
Sno
FROM
studentcourse
WHERE
Cno = '2'
);
26.-- 查询选修了全部课程的学生姓名(没有一门课是他不选修的)
SELECT
Sname
FROM
student
WHERE
NOT EXISTS (
SELECT
*
FROM
course
WHERE
NOT EXISTS (
SELECT
*
FROM
studentcourse
WHERE
Sno = Student.Sno
AND Cno = course.Cno
)
);
27.-- 查询至少选修了学生2016001选修的全部课程的学生号
SELECT DISTINCT
Sno
FROM
studentcourse sc1
WHERE
NOT EXISTS (
SELECT
*
FROM
studentcourse sc2
WHERE
sc2.Sno = '2016001'
AND NOT EXISTS (
SELECT
*
FROM
studentcourse sc3
WHERE
sc3.Sno = sc1.Sno
AND sc3.Cno = Sc2.Cno
)
);
-- 数据更新:插入,删除,修改
-- 插入:insert into <表名> [属性列1,属性列2...] values (value1,value2...)
-- 修改:update <表名> set <列名>=<表达式> [,<列名>=<表达式>]... [where <条件>];
-- 删除:delete from <表名> [where <条件>];