准备 导入数据
--班级表
create table if not exists class(
id tinyint unsigned primary key auto_increment,
name varchar(20) not null,
`desc` varchar(255),
- 反引号(`)用于包裹字段名 desc ,因为 desc 是 SQL 保留字(常用于 ORDER BY 子句表示降序)。通过反引号包裹,可避免数据库将其识别为保留字而引发语法错误,确保字段名的合法性与唯一性。
createdAt timestamp default current_timestamp,
updatedAt timestamp default current_timestamp on update current_timestamp
- on update current_timestamp :当记录更新时,自动刷新
);
insert into class(name,`desc `)values('一班’,'火箭班);
insert into class (name,`desc`) values('二班’,‘平行班');
insert into class(name,`desc`)values('三班’,‘实验班”);
insert into class (name,`desc`)values('四班’,‘待定班');
create table if not exists student(--学生表
id int unsigned primary key auto_increment,
name varchar(20) not null,
age tinyint unsigned not null,
gender enum('男‘,’女’,‘保密’)default‘保密’,
class_id tinyint unsigned,
createdAt timestamp default current_timestamp,
updatedAt timestamp default current_timestamp on update current_timestamp,
foreign key(class_id) references class(id) on update cascade on delete set null
);
FOREIGN KEY(class_id)
含义:声明当前表的 `class_id` 字段为外键。
作用:该字段的值必须引用另一张表的某个字段。
`ON UPDATE CASCADE`
含义:当父表的 `id` 被修改时,子表的 `class_id` 自动同步更新。
`ON DELETE SET NULL`
含义:当父表的某条记录被删除时,子表中对应的 `class_id` 自动设为 `NULL`。
insert into student (name, age, gender, class_ id)values('张三',20,'男',1);
insert into student (name, age, gender, class_id)
values('李四’,19,‘女',1);
insert into student(name, age, gender, class_id)
values ('王五', 21,'女',2);
insert into student (name, age, gender, class_id)
values('赵六’,18,'女',2);
insert into student(name, age, gender, class_id)
values('孙七’,19,‘男',3);
insert into student(name,age,
gender,class_id)values ('周八',19,'男',3);
insert into student (name, age, gender)values('张三丰',15,'男');
直接查询
只需要在单表查询基础上增加一张表即可,返回的结果是多张表的表数据个数的乘积,会有冗余数
据
select* from student;
select * from class;
select* from student, class;
笛卡尔积(Cartesian Product)
-定义:多表查询时,若未指定连接条件,结果集是两表行数的乘积。
-示例:
- `student` 表有 3 行,`class` 表有 2 行 → `SELECT * FROM student, class` 返回 3×2=6 行。
- 问题:数据冗余,大部分结果无实际意义。
select * from student, class where student.class_id = class.id;
作用**:通过 `WHERE` 条件过滤冗余数据,仅保留关联记录。
结果:仅返回 `student.class_id` 与 `class.id` 匹配的行。
内连接查询(INNER JOIN或 JOIN)
内连接的查询结果和直接查询的结果是一样的
内连接(`INNER JOIN` 或 `JOIN`)用于从两个或多个表中仅返回满足连接条件的行。
select * from student;
select * from student join class;
未指定连接条件,会产生笛卡尔积(所有可能的组合),结果通常无意义。
select * from student join class on student.class_id = class.id;
-- select id, name from student join class on student.class_id =class.id;--报错
原因:`id` 和 `name` 可能同时存在于 `student` 和 `class` 表中,数据库无法区分。
- 解决方法:显式指定列所属的表名或别名。
正确写法:
select student.id, class.name from student join class on student.class_id = class.id;
select stu.id, cls.name from student stu join class cls on stu.class_id = cls.id;
取别名
外连接查询
左外连接查询(LEFT OUTER JOIN或 LEFT JOIN)
左边的表是不看条件的,无论条件是否满足,都会返回左表中的所有数据
只有右边的表会看条件,对于右表,只有满足条件的,才会返回,如果不满足条件,右表的所有字段会用 `NULL` 填充。
select * from student left join class on student.class_id = class.id;
右外连接查询(RIGHT OUTER JOIN或 RIGHT JOIN)
右边的表是不看条件的,无论条件是否满足,都会返回右表中的所有数据
只有左边的表会看条件,对于左表,只有满足条件的,才会返回
select * from student right join class on student.class_id = class.id;
UNION查询
在纵向上将多张表的查询结果拼接起来返回
必须保证多张表查询的字段个数一致
select id,name from student union select id,name from class;
子查询
将一个查询语句查询的结果作为另一个查询语句的条件来使用
select class_id from student where id = 3;
select class_id from student where id >= 3;
select name from class where id =(select class_id from student where id = 3);
select name from class where id in (select class_id from student where id >= 3);
外层查询
将一个查询语句查询结果作为另一个查询语句的表来使用
必须给子查询起别名
select name from class where id >= 2;
select * from (select name from class where id >= 2) t;
- 执行逻辑:
1. 先执行子查询 (select name from class where id >= 2) ,这一步与第一个语句相同,得到一个包含 name 列的临时结果集。
2. 必须给这个临时结果集起别名(这里是 t ),否则 SQL 引擎无法识别和引用它。
3. 外层查询 select * from t 表示从别名 t 的临时结果集中获取所有列(由于子查询只返回 name 列,因此实际只返回 name 列)。