查询进阶
- 数据库约束
- 约束类型
- NULL , DEFAULT , UNIQUE 约束
- 主键约束
- 外键约束
- 聚合查询
- 聚合函数
- group by子句
- HAVING
- 联合查询
- 内连接
- 外连接
- 自连接
- 子查询
- 单行子查询
- 多行子查询
数据库约束
约束类型
NOT NULL
#表示某行不能储存空值
UNIQUE
#保证每一行必须有唯一的值
DEFAULT
#规定没有给列赋值时的默认值
PRIMARY KEY
#NOT NULL 和 UNIQUE 的结合 确保某列(或两个列多个列的结合)有
#唯一标识,有助于更容易更快速地找到表中的一个特定的记录
FOREIGN KEY
#保证一个表中的数据匹配另一个表中的值的参照完整性
CHECK
#保证列中的值符合在指定的条件 对于MySQL数据库,对CHECK子句进行分析,但是忽略
#CHECK子句
NULL , DEFAULT , UNIQUE 约束
CREATE TABLE student(id INT NOT NULL,sn INT UNIQUE,name VARCHAR(20) DEFAULT 'unkown',qq_mail VARCHAR(20)
);
主键约束
CREATE TABLE student (id INT NOT NULL PRIMARY KEY,sn INT UNIQUE,name VARCHAR(20) DEFAULT 'unkown',qq_mail VARCHAR(20)
);
对于整数类型的主键,常配搭自增长auto_increment来使用。插入数据对应字段不给值时,使用最大值+1。
即在设定主键约束后加auto_increment
CREATE TABLE student (id INT NOT NULL PRIMARY KEY auto_increment,sn INT UNIQUE,name VARCHAR(20) DEFAULT 'unkown',qq_mail VARCHAR(20)
);
外键约束
在数据库中,外键约束(Foreign Key Constraint)用于建立表与表之间的关系,通过将一个表的列与另一个表的主键或唯一键相关联来定义这种关系。外键约束有助于维护数据的完整性和一致性。
在使用外键约束时,有两个重要的角色:主表
和从表
。主表
包含被引用的主键或唯一键列,而从表
包含外键列,该列引用主表中的主键或唯一键列。
通过使用外键约束,可以确保在插入或更新数据时,从表的外键值必须存在于主表的关联列中。这有助于维护数据的完整性,并确保相关表之间的一致性。
举例
create table classes(id int primary key auto_increment,name varchar(20),`desc` varchar(100)
);create table student(int id primary key auto_increment,sn int unique,name varchar(20) default 'unkown',qq_mail varchar(20),classes_id int,foregin key (classes_id) references classes(id);
);
用上述代码创建学生表和班级表
我们在学生表的最后添加了外键约束让student表中的classes_id字段和classes表中的id字段连接起来
此时student表称为从表
,classes表称为主表
我们可以通过show create table 表名来查看创建表的信息
我们查看student表的创建信息
我们发现倒数第二行专门来描述约束
CONSTRAINT
student_ibfk_1
FOREIGN KEY (classes_id
) REFERENCESclasses
(id
)
CONSTRAINT来表示约束
student_ibfk_1 第一个字段studetn
是表名 第二个字段ibfk
是InnoDB Foreign Key的缩写 表示存储引擎是innoDB 且是外键约束,字段_1
是计数 表示是第一个约束
那么外键约束有什么作用呢?
我们先往班级表中插入几条数据
接着我们尝试向学生表中插入数据
在插入前几条数据时 都可以正常插入 但是我们在插入最后一条数据时 出现了错误
根据报错信息我们可以知道是由于外键约束 我们插入的classes_id 为5 但是在主表classes中只有1-4的班级id 因此出现的报错
这时我们会想到 如果现在删除classes表中的数据 会不会对student表中的数据产生影响
**我们发现还出现的报错 **
**所以我们可以得出结论 外键约束对于主表和从表都存在约束 **
聚合查询
聚合函数
函数 | 说明 |
---|---|
COUNT([DISTINCT] expr) | 返回查询到的数据数量 |
SUM([DISTINCT] expr) | 返回查询到的数据的总和 不是数字没有意义 |
AVG([DISTINCT] expr) | 返回查询到的数据的平均值 不是数字没有意义 |
MAX([DISTINCT] expr) | 返回查询到的数据的最大值 不是数字没有意义 |
MIN([DISTINCT] expr) | 返回查询到的数据的最小值 不是数字没有意义 |
group by子句
SELECT 中使用 GROUP BY 子句可以对指定列进行分组查询。
需要满足:使用 GROUP BY 进行分组查询时,SELECT 指定的字段必须是“分组依据字段”,其他字段若想出现在SELECT 中则必须包含在聚合函数中。
准备测试表
create table emp(id int primary key auto_increment,name varchar(20) not null,role varchar(20) not null,salary numeric(11,2)
);
insert into emp(name, role, salary) values
('马云','服务员', 1000.20),
('马化腾','游戏陪玩', 2000.99),
('孙悟空','游戏角色', 999.11),
('猪无能','游戏角色', 333.5),
('沙和尚','游戏角色', 700.33),
('隔壁老王','董事长', 12000.66);
查询每个角色的平均工资 最大工资和最小工资
HAVING
GROUP BY 子句进行分组以后,需要对分组结果再进行条件过滤时,不能使用 WHERE 语句,而需要用 HAVING
where是对分组前的数据进行筛选
having是对分组后的数据进行筛选
联合查询
实际开发中往往数据来自不同的表,所以需要多表联合查询。多表查询是对多张表的数据取笛卡尔积:
内连接
select 字段 from 表1 别名1 [inner] join 表2 别名2 on 连接条件 and 其他条件;
select 字段 from 表1 别名1,表2 别名2 where 连接条件 and 其他条件;
外连接
外连接分为左外连接和右外连接。如果联合查询,左侧的表完全显示我们就说是左外连接;右侧的表完
全显示我们就说是右外连接。
-- 左外连接,表1完全显示
select 字段名 from 表名1 left join 表名2 on 连接条件;
-- 右外连接,表2完全显示
select 字段 from 表名1 right join 表名2 on 连接条件;
自连接
自连接是指在同一张表连接自身进行查询
例如显示所有"计算机原理"成绩比"Java"成绩高的信息
#第一步先在course表中找到计算机原理和java课程的id号
select * from course where name='计算机原理' or name = 'Java'#再查询成绩表中,“计算机原理”成绩比“Java”成绩 好的信息
select *
from score s1, score s2
where s1.student_id = s2.student_id
and s1.course_id = 3
and s2.course_id = 1
and s1.score > s2.score;
上述操作我们分成两步执行 且没有显示学生信息
SELECTstu.*,s1.score Java,s2.score 计算机原理
FROMscore s1JOIN score s2 ON s1.student_id = s2.student_idJOIN student stu ON s1.student_id = stu.idJOIN course c1 ON s1.course_id = c1.idJOIN course c2 ON s2.course_id = c2.idAND s1.score < s2.scoreAND c1.NAME = 'Java'AND c2.NAME =
子查询
子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询
单行子查询
查询与"不想毕业"同学的同班同学
select *
from student
where classes_id = (select classes_idfrom studentwhere name = '不想毕业'
);
多行子查询
返回多行记录的子查询
查询"语文"或"英文"课程的成绩信息
select *
from score
where course_id in (select idfrom coursewhere name = '语文' or name = '英文'
);
若要查询不在范围内的只需要在in之前 加 not