数据库常用SQL操作--增删改查

数据库经常用到的增删改查语句如下(主要为查询),根据《数据库系统概论》书籍整理,少许修改。其中最重要的是聚集函数的使用(经常与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 <条件>];

猜你喜欢

转载自blog.csdn.net/m0_37568814/article/details/82918957