概念:
mysql提供的机制,辅助我们自动的依赖程序,对数据进行检查。一旦把约束确定好了,后续在进行增删改查时,mysql就会自动的对修改的数据做出检查,看这个数据是否满足约束,如果不满足,就会报错
1. 约束类型
NOT NULL - 指示某列不能存储 NULL 值。
UNIQUE - 保证某列的每行必须有唯一的值。
DEFAULT - 规定没有给列赋值时的默认值。
PRIMARY KEY - NOT NULL 和 UNIQUE 的结合。确保某列(或两个列多个列的结合)有唯一标识,有助于更容易更快速地找到表中的一个特定的记录。
FOREIGN KEY - 保证一个表中的数据匹配另一个表中的值的参照完整性。
CHECK - 保证列中的值符合指定的条件。对于MySQL数据库,对CHECK子句进行分析,但是忽略CHECK子句(java4 不考虑)
1. NULL约束
-- 创建表时,可以指定某列不为空
DROP TABLE IF EXISTS student;
CREATE TABLE student (
id INT NOT NULL,
sn INT,
name VARCHAR(20),
qq_mail VARCHAR(20)
);
2. UNIQUE:唯一约束
-- 重新设置学生表结构
DROP TABLE IF EXISTS student;
CREATE TABLE student (
id INT NOT NULL,
sn INT UNIQUE,
name VARCHAR(20),
qq_mail VARCHAR(20)
);
3. DEFAULT:默认值约束
CREATE TABLE student (
id INT NOT NULL,
name VARCHAR(20) DEFAULT '未命名',
);
4. PRIMARY KEY:主键约束
主键就是一条数据的身份标识,根据这个主键可以唯一确定某个数据。
CREATE TABLE student (
id INT NOT NULL PRIMARY KEY,
name VARCHAR(20)
);
-- 主键是 NOT NULL 和 UNIQUE 的结合,可以不用 NOT NULL
id INT PRIMARY KEY auto_increment
关于自增主键的最大值
5. FOREIGN KEY:外键约束
foreign key (字段名) references 主表(列)
-- 字段名表示【当前这个表的那一类要收到约束】
失败,因为设置外键的时候,会导致子表操作时频繁地查询父表,这个操作十分耗时,为了加快查询速度,如果父表中的某一列带有索引的话,就很方便找。后来干脆,规定,没有索引,就不能建立外键约束
primary key 和 unique 这两个约束,自带索引。
6. CHECK约束(了解)
写一个具体的条件表达式,当前的记录符合条件,就是可以插入/修改的,不符合条件,就失败。但对于mysql5来说,check并不支持(写上不会报错,但也没什么用),故忽略该约束
create table test_user (
id int,
name varchar(20),
sex varchar(1),
check (sex ='男' or sex='女')
);
设计数据库的表,就需要先把实体和关系梳理清楚。实体/对象是从需求场景中,提炼出的一些关键性质的名词,能够描述出学生和班级的相关信息
组句:一个学生可以有一个教务系统账号,但是一个教务系统账号只能归一个学生所有
组句:一个同学只能在一个班级里,但是一个班级可以有很多个学生
组句:一个同学可以选择多门课程来学习,一门课程,也可以被多个同学来选择
单个独自美丽也很好
-- 把select查询出来的结果数据,插入到另一个表中
-- 此时select查询的结果,需要和插入的表,能一一对应
INSERT INTO table_name [(column [, column ...])] SELECT ...
CREATETABLE test_user (
id INT primary key auto_increment,
name VARCHAR(20) comment '姓名',
age INT comment '年龄',
email VARCHAR(20) comment '邮箱',
sex varchar(1) comment '性别',
mobile varchar(20) comment '手机号'
);
-- 将学生表中的所有数据复制到用户表
insertinto test_user(name, email) select name, qq_mail from student;
查询的时候带表达式,本质是列和列之间进行运算,而行与行之间的运算需要使用聚合查询,聚合查询依托于聚合函数
sql中,聚合函数必须和()紧挨在一起
1.聚合函数
函数 | 说明 |
COUNT([DISTINCT] expr) | 返回查询到的数据的数量 |
SUM([DISTINCT] expr) | 返回查询到的数据的总和,不是数字没有意义 |
AVG([DISTINCT] expr) | 返回查询到的数据的平均值,不是数字没有意义 |
MAX([DISTINCT] expr) | 返回查询到的数据的最大值,不是数字没有意义 |
MIN([DISTINCT] expr) | 返回查询到的数据的最小值,不是数字没有意义 |
1.COUNT
空值不会被算入数字个数之中
-- 统计班级共有多少同学
SELECT COUNT(*) FROM student; -- 一共有多少行
SELECT COUNT(0) FROM student;
-- 统计班级收集的 qq_mail 有多少个,qq_mail 为 NULL 的数据不会计入结果SELECT
COUNT(qq_mail) FROM student;
2.SUM
-- 统计数学成绩总分
SELECTSUM(math) FROM exam_result;
-- 不及格 < 60 的总分,没有结果,返回 NULL
SELECTSUM(math) FROM exam_result WHERE math < 60;
3.AVG
-- 统计平均总分
SELECT AVG(chinese + math + english) 平均总分 FROM exam_result;
4.MAX
-- 返回英语最高分
SELECT MAX(english) FROM exam_result;
5.MIN
-- 返回 > 70 分以上的数学最低分
SELECT MIN(math) FROM exam_result WHERE math > 70;
2.分组查询
1. 概述
使用场景:希望把数据分成多组来进行计算,这时候可以通过GROUP BY来实现
使用方法:group by 通过指定一个列,可以按照这一列进行分组,而这一列中,数值相同的行,会被分到一组。而每个分组,都可以使用聚合函数进行计算。
注意:select中指定的列,必须是当前group by 指定的列,如果select 中想用到其他的列,其他的列必须放到聚合函数中,不然查询的结果,会无意义
-- 语法
select column1, sum(column2), .. from table group by column1,column3
2.分组之前的条件 where
-- 求每个岗位的平均薪资,除了张三
select role, avg(salary) from emp where name != '张三' group by role;
2.分组之后的条件 having
分组之后的条件,也是要搭配聚合函数来使用的
select role, avg(salary) from emp group by role having avg(salary) < 20000;
3.分组前,分组后都包含
先执行where,在执行group by,然后select查询,最后是having
select role, avg(salary) from emp where name != '张三' group by role having avg(salary) < 20000;
使用场景:需要结合多个表的数据,进行一些综合性更强的查询
概念:多表查询是对多张表的数据取笛卡尔积,不管是内连接还是外连接都需要用到笛卡尔积
缺点:笛卡尔积是一个非常低效的操作,尤其是当每个表的数据都比较多的时候,也因此,多表联合查询也是一个非常低效的操作(数据少的时候,执行笛卡尔积的过程确实也快,但是控制打印台会一条一条打印,要花费时间)
笛卡尔积
联合查询操作步骤(示例是内连接的一种)
1. 内连接
-- 语法
select 字段 from 表1 别名1 [inner] join 表2 别名2 on 连接条件 and 其他条件;
select 字段 from 表1 别名1,表2 别名2 where 连接条件 and 其他条件
2. 外连接
3. 自连接
本质上是自己和自己笛卡尔积,将“行之间的关系”转换成“列之间的关系”,因为sql无法进行“行与行之间的比较”
操作步骤
select * from score as s1, score as s2; --正确
select * from score, score; -- 错误
select * from score as s1, score as s2 where s1.stident_id = s2.student_id;
4. 子连接
本质上是把多个SQL合并为一个SQL,但这会让代码变得复杂,所以尽量不要使用
简单版本(分两步,化繁为简)
select name from student where classes_id = 1 and name != '不想毕业';
子查询版本(化简为繁,不支持)
select name from student where classes_id = (select classes_id from student where name = '不想毕业') and name != '不想毕业';
5. 合并连接
把多个select所查询得到的结果集合成一个,前后查询的结果集中,结果集的列需要一致
-- 查询id小于3,或者名字为“英文”的课程:
select * from course where id<3
union
select * from course where name='英文';
-- 或者使用or来实现
select * from course where id<3 or name='英文';
-- 查询id小于3,或者名字为“Java”的课程
select * from course where id<3
union all
select * from course where name='英文';