表关系
表关系:表与表之间(实体)有什么样的关系,每种关系应该如何设计表结构。
一对一
1:1
一对一:一张表中的一条记录与另外一张表中最多有一条明确的关系:通常,此设计方案保证两张表中使用同样的主键即可
学生表
学生ID(PRI) | 姓名 | 年龄 | 性别 | 籍贯 | 婚否 | 住址 |
|
|
|
|
|
|
|
表的使用过程中:常用的信息会经常去查询,而不常用的信息会偶尔才会用到。
解决方案:将两张表拆分,常见的放一张表,不常见的放一张表
常用表
学生ID(PRI) | 姓名 | 年龄 | 性别 |
|
|
|
|
不常用表
学生ID(PRI) | 籍贯 | 婚否 | 住址 |
|
|
|
|
一对多
1:N 或者 N:1
一对多,通常也叫作多对一的关系。通常一对多的关系设计的方案,在“多”关系的表中去维护一个字段,这个字段是“一”关系的主键。
班级表 学生表
一对多或者是多对一 应该是多的这一个表中 要新建一个字段来保存一端的所属ID
多对多
多对多:一张表中的一条记录在另外一张表中可以匹配到多条记录,反过来也一样。
多对多的关系如果按照多对一的关系维护:就会出现一个字段中有多个其他表的主键,在访问的时候就会带来不便。
既然通过两张表自己增加字段解决不聊问题,那么就通过第三张表来解决。
多对多解决方案;增加一个中间表,让中间表与对应的其他表形成两个多对一的关系:多对一的解决方案是在“多”表中增加“一”表对应的主键字段。
外键
概念
关键字:foreign key,也叫作外键约束!
如果一个实体A的某个字段,刚好指向或者引用到另外一个实体B的主键,那么实体A的这个字段就是外键!
所以,简单来说,外键就是外面的主键,就是指向其他表的主键的那个字段!
作用
思考:为什么要有外键约束?
外键的意义就是用来约束关系内的实体,而且比较符合现实中的正常的业务逻辑!
所以,外键约束的作用主要就体现在以下的两个方面:
1, 增加子表记录的时候,是否有与之相对应的父表的记录
2, 当删除或更改主表记录的时候,从表中与之对应的记录应该如何处理
增加外键
思考:
应该在父表上定义还是在子表上定义?
应该在子表上定义!
Mysql中提供了两种方式增加外键
方案1:在创建表的时候增加外键(类似主键)
基本语法:在字段之后增加一条语句
[constraint `外键名`] foreign key [`索引名`] (外键字段) references 主表(主键);
方案2:在创建表后增加外键
Alter table 子表 add [constraint `外键名`] foreign key [`索引名`] (外键字段) references 主表(主键);
创建外键后会自动增加一个普通索引 可以指定普通索引的名称 也可以让系统分配
删除外键
外键不允许修改,只能先删除后增加
基本语法:alter table 子表 drop foreign key 外键名字;
外键名字可以通过 show create table table_name 查看
注意:
外键不能删除产生的普通索引,只会删除外键自己
外键约束的概念
可以在创建外键的时候,对外键约束进行选择性的操作。
基本语法: Alter table 从表 add [constraint `外键名`] foreign key [`索引名`] (外键字段) references 主表(主键) on 约束模式;
约束模式有三种:
1、 district:严格模式,默认的,不允许操作
2、 cascade:级联模式,一起操作,主表变化,从表数据跟着变化
3、 set null:置空模式,主表变化(删除),从表对应记录设置为空:前提是从表中对应的外键字段允许为空
外键约束主要约束的对象是主表操作:从表就是不能插入主表不存在的数据
通常在进行约束时候的时候,需要指定操作:update和delete
常用的约束模式: on update cascade, on delete set null,更新级联,删除置空
外键需要注意的问题
ü 外键约束,只能在 当前的 mysql的的 innodb 表类型(引擎)下才会生效!
ü 外键字段需要保证与关联的主表的主键字段类型完全一致
ü 因为外键有非常强大的数据约束作用,而且可能导致数据在后台变化的不可控。导致程序在进行设计开发逻辑的时候,没有办法去很好的把握数据(业务),所以外键比较少使用。
高级数据插入与查询操作
数据的操作也叫作CURD
C:create (创建)
U:update (更新)
R:Retrieve (读取)
D:delete (删除)
插入数据
标准语法:
insert into 表名(字段列表) values(值列表);
扩展语法:
insert into 表名 set 字段1 = 值1,字段2=值2,字段n=值n;
一条insert into可以插入多条记录
语法:
insert into 表名(字段列表) values(值列表), (值列表), (值列表);
蠕虫复制
就是在已有的数据的基础之上,将原来的数据进行复制,插入到对应的表中!
语法规则:
将后面的表中的所有的数据查询出来后作用前面表里面的值
insert into 表名(字段列表) select *|字段列表 from 表名;
下图所示:将B表中的记录插入到A表中
将A表中所有的记录作为值来插入到A表
主键重复
思考:
在进行数据插入的时候,主键已经存在,但是又需要将最新的数据更新到数据表中,怎么办?
语法规则:
insert into 表名(字段列表) values(值列表) 字段1=新值1,字段2=新值2……;
查询数据
查询数据是整个业务逻辑中使用的最多而且也是最复杂的!
select [字段表达式列表子表] [from子句] [where 子句] [group by 子句] [having 子句] [order by子句] [limit 子句]
七子句
from子句的后面的子句称五子句
注意它们的书写不能乱。
字段表达式列表子句
5+10
$v1=10;
now()
表达式与字段别名
使用as关键字为字段起别名
as关键字可以省略
凡是涉及到表达式到一定会牵扯到一个问题:优先级
from子句
表示查询的来源,就是表!
1, 可以写表名列表,使用逗号分割 from可以有多个表 每一个表之间使用逗号分割
如果此时没有条件,相当于形成了一个 笛卡尔积!
A集合的每个元素,都与B集合的每个元素之间有个关联!
A表的所有记录,都与B表的所有记录之间存在关联!
出现了同样的字段名 可以给字段取别名
2, 表的别名
如果多次出现 表名.字段名的情况,可以为表名起别名!
3, dual 虚拟表
where子句
where 条件表达式
省略where子句,相当于永远为真
比较运算符
> < >= <= != =
模糊查询
like。数据
可以使用 % 和 _ 作为通配符
not like,不像like取反!
between and
范围比较,而且是闭区间!
比如,between 5 and 10,相当于数学上的[5,10]
in与not in
都属于集合运算符,用于判断前面的元素是否在或不在一个集合当中!
批量删除这个操作用的特别多
in,在某个集合之内
in (元素列表)
not in,不在某个集合内
not in (元素列表)
null 值的判断
不能使用普通的运算符,因为运算的结果都是null,而且不能作为查询条件!
应该使用 is null 或者 is not null 来判断!
下图是:is null
下图是:is not null
函数 (isnull())也可以完成类似的判断:
注意:运算符也有的优先级的概念,注意可以使用 () 来修改优先级!
select 语句
group by子句
语法
对查询结果(已经通过where子句过滤之后的数据),按照某个字段,进行分组!
语法:where 1 group by 字段!
在分组的结果中,只会显示组内的头一条记录!因此,通常,分组之后的数据,除了分组的字段外,其他字段的逻辑含义很轻!
分组的作用,不在查询每个组内的具体数据。而其作用主要是在分组统计上
统计函数(聚合函数)
count():求某个组内非null记录的个数,通常就用count(*)来表示 统计记录数。典型的使用是 count(*),但是除了*之外,是可以使用字段名的!
其中,只要记录存在,则count(*)就会统计到数据,而如果相应的字段为null,则count(字段)不会统计上数据:
下图是使用count(*)来表示
sum():求和,先根据某个或某几个字段进行分组,然后再对每一个组的某个字段进行相加!
max():求某个组内某个字段的最大值
min():求某个组内某个字段的最小值
avg():求某个组内某个字段的平均值
以班级进行分组后 只会显示组成第一个条记录
group_concat()
分组后排序
分组成默认是升序 ASC DESC 降序
语法:
字段名 ASC(默认)|DESC
多字段分组
group by 字段1,字段2……
回溯(su)统计
其实就是向上统计!
在进行分组统计的时候,往往需要做向上统计!
比如,先统计各个班的最高分,然后就可以将各个班的最高分再进行一次统计,可以得到全年级的最高分!
在MySQL中,也支持回溯统计,其实就是在group by语句的后面加上with rollup即可!
having子句
功能上与where类似,都是条件子句!
需求:要找到学生表中Money大于2000块钱 的学生
求每一个班级中平均工资大于2000块的班级
主要的区别,在于执行时机:
执行时机:
where,是开始时,从数据源中检索数据的条件。
而 having,是在筛选,分组之后,在得到的结果中,再次进行筛选的语法!
因此 having的结果 一定是 where 已经 过滤之后的结果!
having它就是为了配合统计函数来使用!