所谓约束就是数据库允许程序员定义一些对数据的限制规则,数据库会在对数据进行操作时按照这些规则对数据进行校验;
约束的本质就是让我们及时发现数据中的错误,更好地保证数据的正确性;
初始情况下,一个表是可以为空的;
但当添加了NOT NULL约束以后,被添加了约束的列就不允许为空了:
默认情况下,表中的数据是可以重复的;
添加了UNIQUE约束后,被指定了唯一值的某列的每行就不可以重复了;
默认的默认值为NULL;
通过default约束可以修改默认值;
主键不可以为空;
主键不可以重复;
一个表中不能有多条主键;
主键作用重要,同时唯一且不可重复,为了方便用户的使用,MySQL提供了“自增主键”;
对于自增主键,如果用户对自增主键所在的列指定了具体的数值,则认为是手动指定;如果用户指定为NULL,则MySQL按照自增规则自动生成;
MySQL中的自增主键,需要记录当前自增的数值,同时保证再次自增之后,主键不可以重复,因此MySQL直接记录当前自增主键的最大值,再进行下一次的自增;
FOREIGN KEY,外键,描述了两张表之间的关联关系;
两张表之间,负责约束的一方,称为父表;被约束的一方,称为子表;
创建2张表:
父表为空时,子表不可以插入数据;
在外键约束下,每次操作数据时,都会首先触发在父表中的查询,父表中存在才能插入/修改成功;
子表和父表之间是相互限制的;
父表对子表的限制是不可以随意插入和修改数据;
子表对父表的限制是不可以随意删除修改数据;
相比于一次查询,这种首先查询父表的操作可能会拖慢执行效率,但如果查询操作能够触发索引,却也可以提高执行效率;
因此在建立外键约束的时候,MySQL要求,引用的父表的列,必须是主键或者是受UNIQUE约束,因为它们自带索引,查询速度也就会快一些;
直接对表中的值做出限制;
表的设计是取决于需求场景的,因此在设计表之前我们首先要明确需求场景;
然后提取出需求中的实体,为每个实体分配一张表,同时需要理清实体与实体之间的关系;
对于实体A而言,只有唯一的实体B与之对应;对实体B而言,只有唯一的实体A与之对应;
例如,一个人只能有一个身份证号,一个身份证号也只对应一个人;
对于实体A而言,可以有多个实体B与之对应;
例如,一个班级可以有多名学生;
实体A有多个实体B与之对应,实体B也有多个实体A与之对应;
把查询结果作为新增的数据;
insert into 表名1 select 列名 from 表名2;
从表名2中查询出来的结果的列数和类型必须与表名1匹配,列名不做要求;
//创建一个学生表
create table student(
-> id int,
-> name varchar(20));
//为学生表插入数据
insert into student values
-> (1,'海绵宝宝'),
-> (2,'派大星'),
-> (3,'蟹老板');
//创建一个学生表2,不在表2中插入数据
create table student2(
-> id int,
-> name varchar(20));
//将从学生表中查询到的数据插入到学生表2中
insert into student2 select * from student;
MySQL中常用的聚合函数主要有:
count(*)可以查询表中所有数据的数量(包括null值);
count(列名)查询时不包含null值的情况;
MySQL中不正确的空格数量可能会引起错误,要特别注意;
null与数字运算的结果仍为null,所以这里null不参与运算;
sum( )参与查询的数据必须为数字,否则就会产生警告;
把表中的若干行,分成几组;
指定某一列作为分组的依据,分组依据的列值相同,则分为一组;
被划分之后的每个组都可以使用聚合函数;
group by 列;
进行聚合查询时,可以指定条件进行筛选;
在聚合之前进行筛选使用where子句;
在聚合之后进行筛选使用having子句;
聚合之前和聚合之后都进行筛选:
聚合前后都进行筛选的情况,其实是首先进行where子句的筛选,然后进行分组查询,最后再进行having子句的筛选;
又称多表查询,意思是把多个表的记录合并到一起,综合进行查询;
笛卡尔积:将两张表中的所有记录进行排列组合,穷举出所有可能情况;
针对多个表j进行联合查询,本质上就是先对多个表进行笛卡尔运算;
笛卡尔积的列数,就是原来两张表的列数之和;笛卡尔积的行数,就是原来两张表的行数之积;
单纯进行笛卡尔运算得到的结果中包含了大量的无效数据,为了最终得到一个有用的数据表,我们指定合理的过滤条件(连接条件),挑出有效数据,这个过程就是联合查询的过程;
SQL中计算笛卡尔积:
select * from 表1,表2;
select 列名 from 表1 join 表2;
举个栗子:(查询海绵宝宝的成绩)
create table classes (id int primary key auto_increment, name varchar(20), `desc` varchar(100));
create table student (id int primary key auto_increment, sn varchar(20), name varchar(20), qq_mail varchar(20) ,
classes_id int);
create table course(id int primary key auto_increment, name varchar(20));
create table score(score decimal(3, 1), student_id int, course_id int);
insert into classes(name, `desc`) values
('信息工程学院2020级1班', '学习了计算机相关知识'),
('生物农业科技学院2019级3班','学习了生物农业相关知识'),
('数学学院2021级3班','学习了数学');
insert into student(sn, name, qq_mail, classes_id) values
('01','海绵宝宝','[email protected]',1),
('02','派大星',null,1),
('05','蟹老板',null,1),
('06','痞老板','[email protected]',2),
('07','章鱼哥',null,2),
('09','嘿','[email protected]',2);
insert into course(name) values
('Java'),('中国传统文化'),('计算机原理'),('语文'),('高阶数学'),('英文');
insert into score(score, student_id, course_id) values
-- 海绵宝宝
(70.5, 1, 1),(98.5, 1, 3),(33, 1, 5),(98, 1, 6),
-- 派大星
(60, 2, 1),(59.5, 2, 5),
-- 蟹老板
(33, 3, 1),(68, 3, 3),(99, 3, 5),
-- 痞老板
(67, 4, 1),(23, 4, 3),(56, 4, 5),(72, 4, 6),
-- 章鱼哥
(81, 5, 1),(37, 5, 5),
-- 嘿
(56, 6, 2),(43, 6, 4),(79, 6, 6);
select * from student,score;
select * from student,score where student.id=score.student_id;
联合查询的另一种写法:select 列名 from 表2 join 表2 on 连接条件;
select 字段 from 表1 别名1 [inner] join 表2 别名2 on 连接条件 and 其他条件;
select 字段 from 表1 别名1,表2 别名2 where 连接条件 and 其他条件;
内连接得到的结果,就是两张表都包含的数据;
左外连接:select 列名 from 表1 left join 表2;
右外连接:select 列名 from 表1 right join 表2;
左外连接,就是以join左侧的表为主,保证左侧的表中的每个记录都体现在结果中,若左侧的记录在右侧表中不存在,则填充null;
右外连接亦然;
一张表连接自身进行查询,自己与自己进行笛卡尔运算;
自连接可以将行与行之间的查询转换成列与列之间的查询;
子查询指:嵌入在其他sql语句中的select语句,也叫嵌套查询;
举个例子:
查询海绵宝宝同学的同班同学:
首先是普通查询,可以分为2步:
需要使用关键字 in;
将两个查询结果合并到一起;
使用集合操作符 union,union all;
使用union和union all时,前后查询的结果集中,字段需要一致。
符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中的重复行;
符用于取得两个结果集的并集。当使用该操作符时,不会去掉结果集中的重复行。
最后,SQL查询中各个关键字的执行先后顺序: from > on> join > where > group by > with > having >select > distinct > order by > limit