• MySQL数据库的增删改查(进阶)


    目录

    数据库约束

    约束类型

    NULL约束

    UNIQUE:唯一约束

    DEFAULT:默认值约束

    PRIMARY KEY:主键约束

    FOREIGN KEY:外键约束

    表的设计

    一对一关系

     一对多关系

    多对多关系

    查询 

    聚合查询

    聚合函数

    GROUP BY子句

    HAVING

    联合查询

    内连接

    外连接

    子查询

    单行子查询:

    多行子查询:

    合并查询


    MySQL数据库管理不仅仅包括基本的增删改查操作,还涵盖了许多进阶主题,如约束、表的设计、聚合查询和联合查询。本文将深入探讨这些高级概念,帮助你更好地理解MySQL数据库。

    数据库约束

    约束类型

    · NOT NULL - 指示某列不能存储 NULL 值。

    · UNIQUE - 保证某列的每行必须有唯一的值。

    · DEFAULT - 规定没有给列赋值时的默认值。

    · PRIMARY KEY - NOT NULL 和 UNIQUE 的结合。确保某列(或两个列多个列的结合)有·     唯一标 识,有助于更容易更快速地找到表中的一个特定的记录。

    · FOREIGN KEY - 保证一个表中的数据匹配另一个表中的值的参照完整性。

    · CHECK - 保证列中的值符合指定的条件。对于MySQL数据库,对CHECK子句进行分析,      但是忽略 CHECK子句。

    NULL约束

    创建表时,可以指定某列不为空:

    1. CREATE TABLE student (
    2. id INT NOT NULL,
    3. sn INT,
    4. name VARCHAR(20),
    5. qq_mail VARCHAR(20)
    6. );

    UNIQUE:唯一约束

    指定sn列为唯一的、不重复的:

    1. CREATE TABLE student (
    2. id INT NOT NULL,
    3. sn INT UNIQUE,
    4. name VARCHAR(20),
    5. qq_mail VARCHAR(20)
    6. );

    DEFAULT:默认值约束

    指定插入数据时,name列为空,默认值unkown:

    1. CREATE TABLE student (
    2. id INT NOT NULL PRIMARY KEY,
    3. sn INT UNIQUE,
    4. name VARCHAR(20) DEFAULT 'unkown',
    5. qq_mail VARCHAR(20)
    6. );

    PRIMARY KEY:主键约束

    指定id列为主键:

    1. CREATE TABLE student (
    2. id INT NOT NULL PRIMARY KEY,
    3. sn INT UNIQUE,
    4. name VARCHAR(20) DEFAULT 'unkown',
    5. qq_mail VARCHAR(20)
    6. );

    对于整数类型的主键,常配搭自增长auto_increment来使用。插入数据对应字段不给值时,使用最大值+1。如下示例:

    id INT PRIMARY KEY auto_increment,

    FOREIGN KEY:外键约束

    外键用于关联其他表的主键或唯一键,如下示例:

    foreign key (字段名) references 主表(列) 

    表的设计

    一对一关系

     一对多关系

    多对多关系

    查询 

    聚合查询

    聚合函数

    常见的统计总数、计算平局值等操作,可以使用聚合函数来实现,常见的聚合函数有:

    函数说明
    COUNT([DISTINCT] expr)返回查询到的数据的数量
    SUM([DISTINCT] expr)返回查询到的数据的总和,不是数字没有意义
    AVG([DISTINCT] expr)返回查询到的数据的平均值,不是数字没有意义
    MAX([DISTINCT] expr)返回查询到的数据的最大值,不是数字没有意义
    MIN([DISTINCT] expr)返回查询到的数据的最小值,不是数字没有意义

    示例:
    COUNT

    1. -- 统计班级共有多少同学
    2. SELECT COUNT(*) FROM student;
    3. -- 统计班级收集的 qq_mail 有多少个,qq_mail 为 NULL 的数据不会计入结果
    4. SELECT COUNT(qq_mail) FROM student;

    SUM

    1. -- 统计数学成绩总分
    2. SELECT SUM(math) FROM exam_result;
    3. -- 不及格 < 60 的总分,没有结果,返回 NULL
    4. SELECT SUM(math) FROM exam_result WHERE math < 60;

    AVG

    1. -- 统计平均总分
    2. SELECT AVG(chinese + math + english) 平均总分 FROM exam_result;

    MAX

    1. -- 返回英语最高分
    2. SELECT MAX(english) FROM exam_result;

    MIN

    1. -- 返回 > 70 分以上的数学最低分
    2. SELECT MIN(math) FROM exam_result WHERE math > 70;

    GROUP BY子句

    SELECT 中使用 GROUP BY 子句可以对指定列进行分组查询。需要满足:使用 GROUP BY 进行分组查询时,SELECT 指定的字段必须是“分组依据字段”,其他字段若想出现在SELECT 中则必须包含在聚合函数中。

    示例:

    1. create table emp(
    2. id int primary key auto_increment,
    3. name varchar(20) not null,
    4. role varchar(20) not null,
    5. salary numeric(11,2)
    6. );
    7. insert into emp(name, role, salary) values
    8. ('后羿','射手', 2000),
    9. ('孙悟空','打野', 7000),
    10. ('猪八戒','对抗路', 9000),
    11. ('赵云','打野', 6000),
    12. ('金蝉','辅助', 10000);

    查询每个位置的最高经济、最低经济和平均经济

    select role,max(salary),min(salary),avg(salary) from emp group by role;

    HAVING

    GROUP BY 子句进行分组以后,需要对分组结果再进行条件过滤时,不能使用 WHERE 语句,而需要用 HAVING

    显示平均经济低于6000的角色和它的平均经济:

    1. select role,max(salary),min(salary),avg(salary) from emp group by role
    2. having avg(salary)<6000;

    联合查询

    实际开发中往往数据来自不同的表,所以需要多表联合查询。多表查询是对多张表的数据取笛卡尔积:

    关联查询可以对关联表使用别名~~ 

    1. insert into classes(name, `desc`) values
    2. ('计算机系2019级1班', '学习了计算机原理、C和Java语言、数据结构和算法'),
    3. ('中文系2019级3班','学习了中国传统文学'),
    4. ('自动化2019级5班','学习了机械自动化');
    5. insert into student(sn, name, qq_mail, classes_id) values
    6. ('09982','黑旋风李逵','xuanfeng@qq.com',1),
    7. ('00835','菩提老祖',null,1),
    8. ('00391','白素贞',null,1),
    9. ('00031','许仙','xuxian@qq.com',1),
    10. ('51234','好好说话','say@qq.com',2),
    11. ('83223','tellme',null,2),
    12. ('09527','老外学中文','foreigner@qq.com',2);
    13. insert into course(name) values
    14. ('Java'),('中国传统文化'),('计算机原理'),('语文'),('高阶数学'),('英文');
    15. insert into score(score, student_id, course_id) values
    16. -- 黑旋风李逵
    17. (70.5, 1, 1),(98.5, 1, 3),(33, 1, 5),(98, 1, 6),
    18. -- 菩提老祖
    19. (60, 2, 1),(59.5, 2, 5),
    20. -- 白素贞
    21. (33, 3, 1),(68, 3, 3),(99, 3, 5),
    22. -- 许仙
    23. (67, 4, 1),(23, 4, 3),(56, 4, 5),(72, 4, 6),
    24. -- 好好说话
    25. (56, 6, 2),(43, 6, 4),(79, 6, 6),
    26. -- tellme
    27. (80, 7, 2),(92, 7, 6);

    内连接

    语法:

    1. select 字段 from1 别名1 [inner] join2 别名2 on 连接条件 and 其他条件;
    2. select 字段 from1 别名1,表2 别名2 where 连接条件 and 其他条件;

    示例:

    ​​​​​​​(1)查询“许仙”同学的 成绩

    1. select sco.score from student stu inner join score sco on stu.id=sco.student_id
    2. and stu.name='许仙';
    3. -- 或者
    4. select sco.score from student stu, score sco where stu.id=sco.student_id and
    5. stu.name='许仙';

    (2)查询所有同学的总成绩,及同学的个人信息:

    1. -- 成绩表对学生表是多对1关系,查询总成绩是根据成绩表的同学id来进行分组的
    2. SELECT
    3. stu.sn,
    4. stu.NAME,
    5. stu.qq_mail,
    6. sum( sco.score )
    7. FROM
    8. student stu
    9. JOIN score sco ON stu.id = sco.student_id
    10. GROUP BY
    11. sco.student_id;

    (3)查询所有同学的成绩,及同学的个人信息:

    1. -- 查询出来的都是有成绩的同学,“老外学中文”同学 没有显示
    2. select * from student stu join score sco on stu.id=sco.student_id;
    3. -- 学生表、成绩表、课程表3张表关联查询
    4. SELECT
    5. stu.id,
    6. stu.sn,
    7. stu.NAME,
    8. stu.qq_mail,
    9. sco.score,
    10. sco.course_id,
    11. cou.NAME
    12. FROM
    13. student stu
    14. JOIN score sco ON stu.id = sco.student_id
    15. JOIN course cou ON sco.course_id = cou.id
    16. ORDER BY
    17. stu.id;

    外连接

    外连接分为左外连接和右外连接。如果联合查询,左侧的表完全显示我们就说是左外连接;右侧的表完全显示我们就说是右外连接。

    1. -- 左外连接,表1完全显示
    2. select 字段名 from 表名1 left join 表名2 on 连接条件;
    3. -- 右外连接,表2完全显示
    4. select 字段名 from 表名1 right join 表名2 on 连接条件;

    示例:

    查询所有同学的成绩,及同学的个人信息,如果该同学没有成绩,也需要显示

    1. -- “老外学中文”同学 没有考试成绩,也显示出来了
    2. select * from student stu left join score sco on stu.id=sco.student_id;
    3. -- 对应的右外连接为:
    4. select * from score sco right join student stu on stu.id=sco.student_id;
    5. -- 学生表、成绩表、课程表3张表关联查询
    6. SELECT
    7. stu.id,
    8. stu.sn,
    9. stu.NAME,
    10. stu.qq_mail,
    11. sco.score,
    12. sco.course_id,
    13. cou.NAME
    14. FROM
    15. student stu
    16. LEFT JOIN score sco ON stu.id = sco.student_id
    17. LEFT JOIN course cou ON sco.course_id = cou.id
    18. ORDER BY
    19. stu.id;

    子查询

    子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询

    单行子查询

    返回一行记录的子查询,查询与“白素贞” 同学的同班同学:

    1. select * from student where classes_id=(select classes_id from student where
    2. name='白素贞');

    多行子查询

    返回多行记录的子查询,查询“语文”或“英文”课程的成绩信息:

    [NOT] IN关键字:

    1. -- 使用IN
    2. select * from score where course_id in (select id from course where
    3. name='语文' or name='英文');
    4. -- 使用 NOT IN
    5. select * from score where course_id not in (select id from course where
    6. name!='语文' and name!='英文');

    [NOT] EXISTS关键字:

    1. -- 使用 EXISTS
    2. select * from score sco where exists (select sco.id from course cou
    3. where (name='语文' or name='英文') and cou.id = sco.course_id);
    4. -- 使用 NOT EXISTS
    5. select * from score sco where not exists (select sco.id from course cou
    6. where (name!='语文' and name!='英文') and cou.id = sco.course_id);

    在from子句中使用子查询:子查询语句出现在from子句中。这里要用到数据查询的技巧,把一个 子查询当做一个临时表使用。

    查询所有比“中文系2019级3班”平均分高的成绩信息:

    1. -- 获取“中文系2019级3班”的平均分,将其看作临时表
    2. SELECT
    3. avg( sco.score ) score
    4. FROM
    5. score sco
    6. JOIN student stu ON sco.student_id = stu.id
    7. JOIN classes cls ON stu.classes_id = cls.id
    8. WHERE
    9. cls.NAME = '中文系2019级3班';

    查询成绩表中,比以上临时表平均分高的成绩:、

    1. SELECT
    2. *
    3. FROM
    4. score sco,
    5. (
    6. SELECT
    7. avg( sco.score ) score
    8. FROM
    9. score sco
    10. JOIN student stu ON sco.student_id = stu.id
    11. JOIN classes cls ON stu.classes_id = cls.id
    12. WHERE
    13. cls.NAME = '中文系2019级3班'
    14. ) tmp
    15. WHERE
    16. sco.score > tmp.score;

    合并查询

    在实际应用中,为了合并多个select的执行结果,可以使用集合操作符 union,union all。使用UNION 和UNION ALL时,前后查询的结果集中,字段需要一致。

    union:该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中的重复行。

    示例:查询id小于3,或者名字为“英文”的课程:

    1. select * from course where id<3
    2. union
    3. select * from course where name='英文';
    4. -- 或者使用or来实现
    5. select * from course where id<3 or name='英文';

    union all:该操作符用于取得两个结果集的并集。当使用该操作符时,不会去掉结果集中的重复行。

    示例:查询id小于3,或者名字为“Java”的课程

    1. -- 可以看到结果集中出现重复数据Java
    2. select * from course where id<3
    3. union all
    4. select * from course where name='英文';

    本期内容就到这里啦~~😁希望对大家有帮助,喜欢的话可以关注作者噢~🤩

  • 相关阅读:
    【Spring面试】十、SpringBoot相关
    在 Java 中对密码进行哈希处理
    硬盘使用时间如何修改呢
    Qt在Android上设置连接到指定的WIFI
    Shell编程之免交互
    性能测试-性能监控分析与调优(三)《实战》
    怎么降低Linux内核驱动开发的风险?
    实战!接口优化的18种方案
    电力系统数字化升级改造之配电室无人值守
    Three.js
  • 原文地址:https://blog.csdn.net/m0_62468521/article/details/132719453