数据库(三)

前言

本篇博客主要内容为表之间的关系、多表关联、复制表;查询如单表查询、多表关联查询

表之间关系

为什么要分表?

假如现在有两种数据,一种是部门数据一种是员工数据,如果两中数据放在同一张表中则会造成:

  • 数据重复
  • 结构混乱
  • 扩展维护性差
  • 需要分表

所以需要把表中会造成混乱的数据分出来,分成两张表。

mysql> create table dept(id int primary key auto_increment,name char(20),job char(20));
mysql> create table emp(id int primary key auto_increment,name char(20),gender char,age int,salary float,d_id int);

什么时候需要分表?

当出现大量重复数据时,当一条记录中的数据不属于同一类时需要分表。

分表之后产生的问题,员工表可以存储一个不存在的部门编号,这样的数据是不完整的无效数据,必须找到一种方法可以在物理层面建立关联关系。

以上建表语句可以建立逻辑上的关联关系,这有建表的人才明白其中的关系,而 mysql 并不知道关系,所以需要通过外键来进行约束,说明这两张表的关联关系。

外键的使用

mysql> create table 表名(字段名 类型(长度),foreign key(外键的字段名) references 要关联表名(主键名));

使用外键时必须分清主从关系,也就是要分清先键那张表,因为在使用外键关联表时,需要知道对方表的表名,所以要关联的表应该是主表,应该先建主表,这样才能关联起来。

外键的第一个约束

先键主表,再建从表

mysql> create table dept(id int primary key auto_increment,name char(20),job char(20));
mysql> create table emp(id int primary key auto_increment,name char(20),d_id int,foreign key(d_id) references dept(id));

外键的第二个约束

数据先插入主表,再插入从表数据

mysql> insert into dept values(1,'hr','招聘');
mysql> insert into emp values(1,'张无忌',1);

外键的第三个约束

删除数据时先删从表,再删主表

mysql> delete from emp where name = '张无忌';
mysql> delete from dept where id = 1;

外键的第四个约束

从表更新外键时必须保证外键是存在的。

外键的第五个约束

更新主表的 id 时,要么先删除从表关联的数据,或者把关联数据关联到其他的主表 id。

有了这几种约束后,可以保证数据的完整性。相应的受到外键约束,主表的删除和更新操作受到限制,很多情况下,删除主表某个数据需要至少两条sql 语句,会很麻烦。

外键的第六个约束

删除主表时,要先删除从表。

级联操作

删除级联

当主表删除时,从表相关联的记录同步删除

mysql> create table emp(id int primary key auto_increment,name char(20),d_id int,foreign key(d_id) references dept(id) on delete cascade);

更新级联

当主表 id 时,从表相关联的记录通步更新

mysql> create table emp(id int primary key auto_increment,name char(20),d_id int,foreign key(d_id) references dept(id) on update cascade);

级联方向只能是主表级联从表,可以在操作主表时自动操作从表。(单箱操作,主表变化是级联操作从表,从表的变化不会影响主表)

一对一关系

一对一的关系只需要加一个外键来关联即可,但是需要给外键加上唯一约束。有主从关系的都需要先建主表。

mysql> create customer(c_id int primary key auto_increment,name char(20),phonenum char(11),addr char(20));
mysql> create student(s_id int primary key auto_increment,name char(20),class char(11),number char(20),housenum char(20),c_id int unique,foreign key(c_id) references customer(c_id)); 

一对一的另一种使用场景,当一个表的字段太多,而常用的字段不多时,可以采取垂直分表的方式来提高效率,比如个人信息有身份证、性别、年龄、地址等,可以拆分为基础信息和细节信息;也有另一种提升效率的方式,水平分表,当一个表中的数据记录太多时,效率会降低,可以采取水平分表,字段完全相同。

多对多关系

假如有两张表,一张表存的是老师,另一张表存的是学生。因为一个老师可以教多个学生,一个学生也可以有多个老师,所以这是双向多对一的关系,也就是多对多的关系。那么应该怎么存储数据呢?

可以通过增加一个中间表来存储两张表的关系,然后其他两张表分别用一个字段作为外键来关联中间表。(只要是多对多关系都是靠中间表来存储两张表之间的关系)除了中间表,另外两张都是主表,具体先建哪种主表没有先后顺序。多对多关系至少需要三张表。

mysql> create table stu(id int primary key auto_increment,name char(20));
mysql> create table tea(id int primary key auto_increment,name char(20));
mysql> create table tsr(id int primary key auto_increment,t_id int,s_id int,foreign key(t_id) references tea(id),foreign key(s_id) references stu(id));

因为老师和学生都是主表,关系表是从表,所以需要先插入老师和学生的数据,接着插入中间表的数据。

多对多关系表中因为已经有了 id 为主键,所以可以重复存入相同的学生和老师关系数据,可以通过联合主键改变。

多对一关系

mysql> create table dept(id int primary key auto_increment,name char(20),job char(20));
mysql> create table emp(id int primary key auto_increment,name char(20),d_id int,foreign key(d_id) references dept(id));

复制表

mysql> create table 新表名 select * from 被复制的表名;

注意不会复制主键和约束条件,数据结构都可以复制。

mysql> create table 新表名 select * from 源表名 where 1 = 2;

当where 后面条件不成立时,只会复制表结构。

蠕虫复制

自我复制。

mysql> insert into 表名 select * from 表名;

如果有主键

mysql> insert into 表名(其他字段) select 其他字段 from 表名;

在日常开发中,如果对性能要求很高,不应该使用外键

  1. 效率降低
  2. 耦合 关系多起来会造成管理麻烦

这时候关系只是逻辑关系很有可能产生错误数据。

posted @ 2018-11-21 21:24  rsuxwvilc  阅读(443)  评论(0编辑  收藏  举报