0


一文帮你玩转MySQL表---增,删,查,改(进阶)

1. 数据库约束

1.1 约束类型

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

**· UNIQUE **保证某列必须有唯一的值

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

**· PRIMARY KEY **,NOT NULL和UNIQUE的结合,确保某列有唯一标识,有助于更容易更快捷地找到表中的一个特定记录

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

· CHECK 保证列中的值符合指定的条件

1.2 NOT NULL约束

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

  1. create table student(
  2. id int NOT NULL, --id不为空
  3. name varchar(10),
  4. sex varchar(1),
  5. age int
  6. );

1.3 UNIQUE 唯一约束

指定id列为唯一的,不重复:

  1. drop table if exists student;
  2. create table student(
  3. id int UNIQUE, --id为唯一的
  4. name varchar(10),
  5. sex varchar(1),
  6. age int
  7. );

1.4 DEFAULT 默认值约束

指定插入数据时,如果name列为空,则将默认值设为unkown:

  1. drop table if exists student;
  2. create table student(
  3. id int UNIQUE,
  4. name varchar(10) DEFAULT 'unkown',
  5. sex varchar(1),
  6. age int
  7. );

1.5 PRIMARY KEY 主键约束

指定id列为主键:

  1. drop table if exists student;
  2. create table student(
  3. id int PRIMARY KEY,
  4. name varchar(10) DEFAULT 'unkown',
  5. sex varchar(1),
  6. age int
  7. );

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

  1. id int PRIMARY KEY auto_increment,

1.6 FOREIGN KEY 外键约束

外键用于关联其他表的主键或唯一值

语法:

  1. foreign key (字段名) references 主表(列);

示例:

创建班级表:

  1. -- 创建班级表
  2. drop table if exists classes;
  3. create table classes(
  4. id int primary key auto_increment,
  5. name varchar(20)
  6. );

创建学生表,一个学生对应一个班级,一个班级对应多个学生,id为主键,classes_id为外键,关联班级表id:

  1. -- 创建学生表来关联班级表
  2. drop table if exists student;
  3. create table student(
  4. id int PRIMARY KEY,
  5. name varchar(10) DEFAULT 'unkown',
  6. sex varchar(1),
  7. classes_id int,
  8. foreign key (classes_id) references classes(id)
  9. );

1.7 CHECK约束(了解)

MySQL使用时不报错,但忽略该约束:

  1. create table test_user (
  2. id int,
  3. name varchar(10),
  4. sex varchar(1),
  5. check (sex = '男' or sex = '女')
  6. );

2. 表的设计

三大范式:

一对一:

一对多:

多对多:

创建课程表:

  1. drop table if exists course;
  2. create table course (
  3. id int primary key auto_increment,
  4. name varchar(20)
  5. );

创建学生课程中间表,考试成绩表:

  1. drop table if exists score;
  2. create table score (
  3. id int primary key auto_increment,
  4. score decimal(3,1),
  5. student_id int,
  6. course_id int,
  7. foreign key (student_id) references student(id),
  8. foreign key (course_id) references course(id)
  9. );

3. 新增

插入查询的结果

语法:

  1. INSERT INTO table_name [(column [, column ...])] SELECT ...

示例:

新建一张user表:

  1. create table user (
  2. id int primary key auto_increment,
  3. name varchar(10),
  4. sex varchar(1),
  5. age int,
  6. email varchar(20)
  7. );

将学生表的数据复制到user表中:

  1. insert into user (name,sex,age) select name,sex,age from student;

4. 查询

4.1 聚合查询

4.1.1 聚合函数

常见的统计总数,计算平均值等操作,可以使用聚合查询来实现,常见的聚合函数
函数****说明COUNT([DISTINCT] expr)返回查询到的数据的数量SUM([DISTINCT] expr)返回查询到的数据的总和AVG([DISTINCT] expr)返回查询到的数据的平均值MAX([DISTINCT] expr)返回查询到的数据的最大值MIN([DISTINCT] expr)返回查询到的数据的最小值
示例:
· COUNT

  1. -- 统计班级有多少个同学
  2. select count(*) from student;
  3. select count(0) from student;

· SUM

  1. -- 统计学生的数学总成绩
  2. select sum(math) from student_score;
  3. -- 统计不及格学生的数学总成绩
  4. select sum(math) from student_score where math<60;

· AVG

  1. -- 统计平均总分
  2. select avg(chinese+math+english) from student_score;

· MAX

  1. -- 找出英语的最高成绩
  2. select max(english) from student_score;

· MIN

  1. -- 找出语文的最低成绩
  2. select min(chinese) from student_score;

4.1.2 GROUP BY

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

语法:

  1. select column1, sum(column2), .. from table group by column1,column3;

案例表:

  1. create table emp (
  2. id int primary key auto_increment,
  3. name varchar(10),
  4. role varchar(10) comment '角色',
  5. salary decimal(10,2) comment '薪资'
  6. );
  7. insert into emp (name,role,salary) values
  8. ('小王','员工',3000.50),
  9. ('小贺','老板',200000.00),
  10. ('小张','秘书',15000),
  11. ('小方','保洁员',3000),
  12. ('小乔','员工',4500.20),
  13. ('小李','员工',5000.28);

查询每个角色的最高工资,最低工资和平均工资:

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

结果:

4.1.3 HAVING

GROUP BY子句进行分组后,如果要对分组后的结果进行条件过滤不能使用WHERE,要使用HAVING语句。

示例:显示平均工资低于4000的角色,和他的平均工资:

  1. select role,avg(salary) from emp group by role having avg(salary)<4000;

结果:

4.2 联合查询

先将后续用到的表和数据给出:班级表,学生表,课程表,分数表

  1. drop table if exists classes;
  2. create table classes (
  3. id int primary key auto_increment,
  4. name varchar(20)
  5. );
  6. insert into classes (name) values
  7. ('计算机1班'),
  8. ('自动化2班'),
  9. ('机械3班');
  10. drop table if exists student;
  11. create table student (
  12. id int primary key auto_increment,
  13. name varchar(10),
  14. classes_id int,
  15. foreign key (classes_id) references classes(id)
  16. );
  17. insert into student (name,classes_id) values
  18. ('小花',2),
  19. ('小张',1),
  20. ('小贺',1),
  21. ('小方',3),
  22. ('小乔',3);
  23. drop table if exists course;
  24. create table course (
  25. id int primary key auto_increment,
  26. name varchar(20)
  27. );
  28. insert into course (name) values
  29. ('java程序设计'),
  30. ('大学英语'),
  31. ('高等数学'),
  32. ('数据结构'),
  33. ('工程制图');
  34. drop table if exists score;
  35. create table score (
  36. id int primary key auto_increment,
  37. score decimal(3,1),
  38. student_id int,
  39. course_id int,
  40. foreign key (student_id) references student(id),
  41. foreign key (course_id) references course(id)
  42. );
  43. insert into score (score,student_id,course_id) values
  44. -- 小花
  45. (98.5,1,3),(80,1,5),
  46. -- 小张
  47. (99,2,1),(95,2,2),(96,2,3),(90,2,4),(93,2,5),
  48. -- 小贺
  49. (85,3,1),(86,3,2),(86,3,3),(95,3,4),
  50. -- 小方
  51. (70,4,3),(65,4,5),
  52. -- 小乔
  53. (65,5,5),(67,5,3),(68,5,2);

实际的开发中,数据来自不同的表,这时候需要多张表联合查询,多表查询是对多张表的数据取笛卡尔积

笛卡尔积:

**注意:关联查询可以对关联表使用别名 **

4.2.1 内连接

语法:

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

示例:查询“小张”同学的成绩:

  1. select
  2. stu.id,
  3. stu.name,
  4. sco.score
  5. from
  6. student stu
  7. join score sco on stu.id = sco.student_id
  8. and stu.name='小张';

结果:

示例:查询所有同学的总成绩,及同学的个人信息:

  1. select
  2. stu.id,
  3. stu.name,
  4. sum(sco.score)
  5. from
  6. student stu
  7. join score sco on stu.id = sco.student_id
  8. group by
  9. stu.id;

结果:

示例:查询所有同学的成绩,及同学的个人信息:

  1. select
  2. stu.id,
  3. stu.name,
  4. sco.score,
  5. sco.course_id,
  6. cou.name
  7. from
  8. student stu
  9. join score sco on stu.id = sco.student_id
  10. join course cou on sco.course_id = cou.id;

结果:

4.2.2 外连接

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

语法:

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

4.2.3 自连接

自连接是指在同一张表连接自身进行查询

示例:显示所有“大学英语”比“高等数学”成绩高的信息:

  1. select
  2. stu.*,
  3. s1.score 大学英语,
  4. s2.score 高等数学
  5. from
  6. score s1
  7. join score s2 on s1.student_id = s2.student_id
  8. join student stu on s1.student_id = stu.id
  9. join course c1 on s1.course_id = c1.id
  10. join course c2 on s2.course_id = c2.id
  11. and s1.score > s2.score
  12. and c1.name = '大学英语'
  13. and c2.name = '高等数学';

结果:

4.2.4 子查询

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

· 单行子查询:返回一行记录的子查询

示例:查询与“小张”在同一个班的同学

  1. select
  2. *
  3. from
  4. student
  5. where
  6. classes_id = (
  7. select
  8. classes_id
  9. from
  10. student
  11. where
  12. name = '小张'
  13. );

结果:

· 多行子查询:返回多行记录的子查询

示例:查询“高等数学”或“大学英语”课程的成绩信息

1. [NOT] IN 关键字

  1. -- 使用IN
  2. select * from score where course_id in (
  3. select id from course where name='大学英语' or name='高等数学'
  4. );
  5. -- 使用NOT IN
  6. select * from score where course_id not in (
  7. select id from course where name != '高等数学' and name != '大学英语'
  8. );
  1. [NOT] EXISTS 关键字
  1. -- 使用exists
  2. select
  3. *
  4. from
  5. score sco
  6. where
  7. exists (
  8. select
  9. sco.id
  10. from
  11. course cou
  12. where
  13. (
  14. name = '高等数学'
  15. or name = '大学英语'
  16. )
  17. and cou.id = sco.course_id
  18. );
  19. -- 使用not exists
  20. select
  21. *
  22. from
  23. score sco
  24. where
  25. not exists (
  26. select
  27. sco.id
  28. from
  29. course cou
  30. where
  31. (
  32. name != '高等数学'
  33. and name != '大学英语'
  34. )
  35. and cou.id = sco.course_id
  36. );

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

注意:临时表必须起别名,临时表也可以当作一张虚拟表来关联查询

示例:查询所有比自动化2班平均分高的成绩信息

  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 = '自动化2班'
  14. ) tmp
  15. where
  16. sco.score > tmp.score;

结果:

4.2.5 合并查询

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

· UNION

该操作符取得两个结果集的并集,会自动去掉结果集中的重复行

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

  1. select * from course where id < 3
  2. union
  3. select * from course where name = '高等数学';

结果:

· UNION ALL

该操作符取两个结果集的并集,但是不会去掉结果集中的重复行

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

  1. select * from course where id < 3
  2. union all
  3. select * from course where name = 'java程序设计';

结果:


本文转载自: https://blog.csdn.net/qq_58710208/article/details/122232865
版权归原作者 Java猿~ 所有, 如有侵权,请联系我们删除。

“一文帮你玩转MySQL表---增,删,查,改(进阶)”的评论:

还没有评论