第32天 default默认值 unique单列唯一和联合唯一 primary key主键 auto_increment自增 外键foregin key 表与表之间关系

约束条件
之前讲过:
zerofill (填充0)
unsigned (约束条件值unsigned 无符号)
not null 非空(不能插入空)

补充知识点 插入数据的时候可以指定字段

create table t1(
    id int,
    name char(16)
    );
insert into t1(name id)values("nana",1)

default默认值
default代码展示

create table t2(
id int,
name char(16),
gender enum("male","female","other")default"male"
);
insert into t2(id,name)values(1,"nana");   gender显示默认为male
insert into t2 values(2,"dada","female");   gender显示为female
desc t2;
select * from t2;

unique唯一

单列唯一
    create table t3(
    id int unique,
    name char(16)
    );
    insert into t3 values(1,"jason"),(1,"dada");    id两都是1,报错
    insert into t3 values(1,"jason"),(2,"dada");    id是唯一的,正常存储
    desc t3;
    select * from t3;
联合唯一
比如ip和port
单个都可以重复 但是加在一起必须是唯一的
联合唯一代码验证
    create table t4(
        id int,
        ip char(16),
        port int,
        unique(ip,port)
        );
    insert into t4 values(1,"127.0.0.1",8080);
    insert into t4 values(2,"127.0.0.1",8081);
    insert into t4 values(3,"127.0.0.2",8080);
    insert into t4 values(4,"127.0.0.1",8080);  报错
    desc t4;
    select * from t4;

primary key主键
单单从约束效果上来看primary key 等价于not null + unique
非空且唯一!!!

主键代码验证
    create table t5(id int primary key);
    insert into t5 values(null);    报错
    insert into t5 values(1)(1);   报错
    insert into t5 values(1),(2);   正常
    desc t5;
    select * from t5;

它除了有约束效果之外,它还是Innodb存储引擎组织数据的依据、
Innodb存储引擎在创建表的是后必须要有primary key
因为它类似于书的目录 能够帮助提示查询效率并且也是建表的依据

一张表中有且只有一个主键 如果你没有设置主键 那么会从上往下搜索直到
遇到一个非空且唯一的字段将它自动升级为主键

代码演示
    create table t6(
        id int,
        name char(16),
        age int not null unique,
        addr char(32) not null unique
        );
    
    desc t6;  (age key项自动升级为PRI主键)

如果表中没有主键也没有其他任何的非空且唯一字段 那么Innodb会采用自己
内部提供的一个隐藏字段为主键,隐藏意味着你无法使用它,就无法提供查询速度

一张表中通常都应该有一个主键字段 并且通常将id字段作为主键

单个字段主键

代码演示
    create table t7(
        id int primary key,
        name char(16)
        );
    desc t7;

联合主键(多个字段联合起来作为表的主键 本质还是一个主键)

代码演示
    create table t8(
        id int,
        port int,
        primary key(ip,port)
        );
    desc t8;
我们以后在创建表的时候id字段一定要加primary key(数据的唯一标识)

auto_increment自增 (自动去增加数据的编号)
当编号特别多的时候 人为的去维护太麻烦

代码演示
    create table t9(
        id int primary key auto_increment,
        name char(16)
        );
    insert into t9(name) values("jason"),("nana"),("dada");
    select * from t9;
    
注意auto_increment通常都是加在primary key主键上,不能给普通字段加
代码演示
    create table t10(id int auto_increment);    报错
    
总结:
    以后在创建表的id(数据的唯一标识id,uid,sid)字段的时候
    id int primary key auto_increment

补充:
    delete from在删除表中数据的时候,主键的自增不会停止
    truncate t1清空表数据并重置主键
代码演示
    delete from t9;
    insert into t9(name) values("lala");  (id默认是从4开始的)

    truncate t9
    insert into t9(name) values("lala");  (id是重置为0开始的)

表与表之间建关系
定义了一张员工表 表中有很多字段
id name gender dep_name dep_desc

该表的组织结构不是很清晰(可忽视)
浪费硬盘空间(可忽视)
数据的扩展性极差(无法忽视)

如何优化
上述问题就类似于你将所有的代码都写在了一个py文件中
将员工表拆分 员工表和部门表

外键 foregin key
外键就是用来帮助我们建立表与表之间关系的
foregin key

表与表之间最多只有4种关系

一对多关系
    在mysql的关系中没有多对一的说法
    一对多 多对一 都叫一对多
多对多关系
一对多关系
没有关系

一对多的关系
判断表与表之间关系的方法,前期不熟悉的情况下,一定要按照换位思考的原则,分别站在两张表的角度考虑

员工表与部门表为例
思考一个员工能否对应多个部门(一条员工数据能否对应多条部门数据)
不能
(不能直接得出结论 一定要两张表都考虑完全)
再站在部门表
思考一个一个部门能否对应多个员工(一个部门的数据能否对应多条员工数据)

得出结论
员工表与部门表是单向的一对多
所以表关系就是一对多

foreign key
1 一对多表关系 外键字段建在多的一方
2 在创建表的时候 一定要先建被关联表
3 在录入数据的时候 也必须先录入被关联表
在这里插入图片描述

sql语句建立表关系

  create table dep(
        id int primary key auto_increment,
        dep_name char(16),
        dep_desc char(32)
        );      (部门表)
        
    create table emp(
        id int primary key auto_increment,
        name char(16),
        gender enum("male","female","other") default "male",
        dep_id int,
        foreign key(dep_id) references dep(id)
        );      (员工表)

    desc dep;
    desc emp;
    

    insert into emp(name,dep_id) values("nana",1);  直接插入emp表会报错,dep_id是外键字段,关联了部门表

    insert into dep(dep_name,dep_desc) values("外交部","流浪法师"),
    ("教学部","教书育人"),
    ("技术部","技术能力部门");
    
    insert into emp(name,dep_id)values("jason",1),
    ("nana",2),("dada",3),("lala",4);   dep表中只绑定3个id,lala绑定第4个id会报错

    insert into emp(name,dep_id)values("jason",1),
    ("nana",2),("dada",3);
    
    select * from dep;
    select * from emp;

修改dep表里面的id字段

update dep set id=200 where id=2;   报错,无法更改

删除dep表里面的数据

delete from dep;    报错,拒绝修改

修改或删除表里面的数据方法:
1 先删除教学部对应的员工数据 之后再删除部门
操作太多繁琐

2 真正做到数据之间有关系
更新就同步更新
删除就同步删除
级联更新 级联删除

foreign key(dep_id) references dep(id) 
on update cascade   # 同步更新(级联更新)
on delete cascade   # 同步删除(级联删除)
create table dep(
    id int primary key auto_increment,
    dep_name char(16),
    dep_desc char(32)
    );

create table emp(
    id int primary key auto_increment,
    name char(16),
    gender enum("male","female","other") default "male",
    dep_id int,
    foreign key(dep_id) references dep(id) 
    on update cascade   # 同步更新(级联更新)
    on delete cascade   # 同步删除(级联删除)
    );

insert into dep(dep_name,dep_desc) values("外交部","流浪法师"),
("教学部","教书育人"),
("技术部","技术能力部门");
insert into emp(name,dep_id)values("jason",1),
("nana",2),("dada",3);

update dep set id=200 where id=2;   # 将id=2的数据修改成id=200
delete from dep where id=1;     # 将id=1的数据删除
select * from dep;
select * from emp;

多对多的关系
图书表与作者表为例
在这里插入图片描述

  create table book(
        id int primary key auto_increment,
        title varchar(32),
        price int,
        author_id int,
        foreign key(author_id) references author(id)
        on update cascade   # 同步更新
        on delete cascade   # 同步删除
        );
        
    create table author(
        id int primary auto_increment,
        name varchar(32),
        age int,
        book_id int,
        foreign key(book_id) references book(id)
        on update cascade   # 同步更新
        on delete cascade   # 同步删除
        );

按照上述的方式创建,双方都是对方的被关联表,没有办法创建成功
其实我们只是想记录书籍和作者的关系
针对多对多字段表关系,不能在两张原有的表中创建外键
需要你单独再开设一张专门用来存储两张表数据之间的关系
在这里插入图片描述

案例代码展示

create table book(
    id int primary key auto_increment,
    title varchar(32),
    price int);

create table author(
    id int primary key auto_increment,
    name varchar(32),
    age int);

create table book2author(
    id int primary key auto_increment,
    author_id int,
    book_id int,
    foreign key(author_id) references author(id)
    on update cascade
    on delete cascade,
    foreign key(book_id) references book(id)
    on update cascade
    on delete cascade);

desc book2author;

    
book表与author表之间没有直接的关系,book2author这张表作为一张媒介表使用。 
book2author中的book_id与book中的id是一个一对多的关系,
book2author中的author_id与author中的id也是一个一对多的关系。
    insert into book(title,price) values("撩妹大法",9999),("独孤九贱",8888);
    insert into author(name,age) values("nana",16),("dada",18);
    
    select * from book;
    select * from author;
    select * from book2author;
    
    delete from book where id=2;
    select * from book2author;      # 删除book表中的id为2的数据,那么book2author表中的跟book表中id为2关联的数据也被删除了

一对一的关系
id name age addr phone hobby email…
如果一个表的字段特别多 每次查询又不是所有的字段都能用得到

将表一分为二 
    用户表
        用户表
            id name age
        用户详情表
            id addr phone hobby email......
站在用户表
    一个用户表能否对应多个用户详情 不能
站在详情表
    一个详情能否属于多个用户 不能
    
   结论:
    单向的一对多都不成立 那么这个时候两者之间的表关系
    就是一对一
    或者是没有关系(好判断)

客户表和学生表
在你们报名之间是客户
在报名之后是学生(期间有一些客户不会报名)
一对一 外键字段建在任意一方都可以 但是推荐建在查询频率比较高的表中
在这里插入图片描述

案例代码演示

   create table authordetail(
        id int primary key auto_increment,
        phone int,
        addr varchar(64)
        );
    
    create table author1(
        id int primary key auto_increment,
        name varchar(32),
        age int,
        authordetail_id int unique,
        foreign key(authordetail_id) references authordetail(id)
        on update cascade
        on delete cascade
        );
    desc author1;
    desc authordetail;
    

总结

表关系的建立需要用foreign key
    一对多
        外键字段建在多的一方
    多对多
        自己开设第三张存储
    一对一
        建在任意一方都可以 但是推荐建在查询频率较高的表中

判断表之间的关系方式
    换位思考!!!
    员工与部门
    图书与作者
    作者与作者详情

修改表(了解)

  mysql对大小写是不敏感的(mysql是不区分大小写的)
    修改表名
        alter table 表名 rename 新表名;
        
    增加字段
        alter table 表名 add 字段名 字段类型(宽度) 约束条件;
        alter table 表名 add 字段名 字段类型(宽度) 约束条件 first;     # 新建字段在最前面
        alter table 表名 add 字段名 字段类型(宽度) 约束条件 after 字段名;     # 新建的字段跟在哪个字段名的后面 
    删除字段
        alter table 表名 drop 字段名;
    修改字段
        alter table 表名 modify 字段名 字段类型(宽度)约束条件;     # 修改字段名中的字段类型或者是约束条件
        
        alter table 表名 change 旧字段名 新字段名 字段类型(宽度)约束条件;   # 更换新的字段名,更换新的字段类型和约束条件

复制表(了解)

我们sql语句的结果其实也是一张虚拟表
	create table 表名 select * from 旧表名;  # 只能复制表结构和数据,不能复制主键 外键 索引...
	create table 表名 select * from 旧表 where 条件;  # 按照条件复制表中的数据建成新表(如果条件不成立,那么会直接复制表结构,数据为空

猜你喜欢

转载自blog.csdn.net/Yosigo_/article/details/113781956