zoukankan      html  css  js  c++  java
  • mysql 中的约束------表与表之间的关系

    约束

    mysql中的约束

    unique:

    ​ 唯一性的约束,表示这个字段不能出现重复的值,用于唯一标识一条记录

    ​ e.g.:身份证,学号

    not null:

    ​ 非空约束,表示这个字段的值不能为空

    ​ e.g.:账户名,密码

    null:

    ​ 一些数据类型默认就是可以为空的

    default:

    ​ 默认值,用于给某一个字段设置默认值

    普通约束

    #完整的建表语句
    create table table_name(字段名称  字段类型【(宽度)约束】charset utf8;
    #学生表
    create table student(
    	#非空
    	name char(10) not null,
    	#默认值
    	gender enum('g','b') default 'b')
    	#唯一
        id int unique)
        
    #测试
    insert into student values(null,null,null)#错误  原因是name不能为空
    insert into student values('jack',null,null)#可以插入,原因是null作为一个特殊的值,并且id的唯一约束也可以为null
    insert into student (name,id)values('jack',null);#可以插入 当没有给gender指定参数时,可以用默认值
    alter table student modify id int unique not null
    #为已经存在的字段添加约束
    

    primary key:

    ​ 主键约束,从约束角度老看就等同于 非空+唯一

    ​ 主键和普通约束的区别在于:

    create table person(
    	id char(19) primary key,
    	name char(20)
    );
    insert into person values('1','rose');#ok
    insert into person values('1','jack')# ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'主键冲突;
    insert into person values('2','jack')#ok
    insert into person values(null,'tomor')
    #Column 'id' cannot be null #主键不能为空
    
    
    #从约束角度来看,等同于,非空+唯一
    #create table person(
    	id char(10),
        name char(20)
        );
    #在innodb存储引擎中,主键用于组织数据(树形结构)
    #也就是说主键对于innodb引擎来说是必要的,没有不行
    #如果没有手动指定主键
    #mysql 会自动查找一个具备非空且唯一的字段作为主键
    #如果没有这样的字段,mysql会创建一个隐藏字段 作为主键
    #首先明确主键是一个索引,unique也是,索引的作用是加速查询
    #如果我们在查询语句中没有使用索引字段,mysql讲无法为我们查询加速,一位置如果没有主键,将无法加速查询
    
    
    总的来说:主键具备约束的作用,还能加快我们的查询速度,所以今后在创建表的时候都应该创建索引字段
    将什么样字段创建主键:
    	#如果本来的业务就存在非空且唯一的字段,那就把他设为主键
        #如果没有那就自己添加一个字段专门作为主键
        
    通常我们将主键设置为类 int 类型  为了方便保证唯一
    案例:
    mysql>create table Pc(
    	id in primary key,
    	pinpai char(20),
    	model char(10),
    	price float
    );
    mysql> insert into PC values(1,"IBM","1214SB",40000);
    mysql> insert into PC values(2,"DELL","1200DSB",4000);
    mysql> select *from PC;
    mysql> select *from PC where id = 1;
    mysql> select *from PC where pp = "DELL";
    

    为主键设置自动增长:

    ​ mysql有一个自动增长的属性,可以添加在整形字段上,每次插入数据时,都可以自动的插入值,并且每次加1不会冲突;

    create table teacher(
    	id int primary key auto_increment,
    	name char(10)
    );
    insert into teacher values(null,'jack');
    #对于自定增长的字段可以给null,会自动生成值
    insert into teacher(name) values('jack');
    #可以跳过这个字段
    

    自动增长可以用在具备索引,并且是数字类型的字段上,但是通常与主键一起使用

    表yu表之间的关系:

    foregin key:外键约束,用于指向另一个表的主键字段

    #创建标的时候添加外键
    create table teacher (
    	id int primary key auto_increment,
    	name char(10),
    	gender char(1),
    	dept_id int,
    	foreign key (dept_id) references dept(id)
    );
    #注解
    foregin key (dept_id) references dept(id)
    #其中dept_id 表示表的外键字段
    #dept 表示要关联哪个表
    #dept(id)  id 表示的是关联的dept表的id字段
    
    先后循序
    先有主表,,再有从表
    先有dept ,,再有teacher
    

    foreign key 带来的约束作用

    1.先从表中插入一条记录,关联了一个主表不存在的id  会导致插入失败
    必须保证部门id(外键的值)必须是在主表中存在的
    2.插入数据的顺序:
    	先主表 再插入从表
    3.从表更新外键时也必须保证 外键的值在主表中是存在的
    4.删除主表记录前,要保证从表中没有外键关联被删除的id
    	-必须先删除从表再删除主表
    5.更新主表记录的主键时,要保证从表中没有外键关联被删除的id
    6.必须先创建主表
    7.删除表  其必先删从表
    

    foreign key 就是用来保证两张表之间的关联是正确的

    练习:班级表和学员表

    主:班级 从:学员

    create table class(
    	id int primary key auto_increment,
    	name char(20),
    );
    create table student(
    	id int primary key auto_increment,
    	name char(20),
    	gender char(1),
    	c_id int,
    	foreign key (c_id) references class(id)
    );
    

    级联操作 cascade

    当我们需要删除主表信息时,必须先删除从表中的关联数据,很麻烦

    那级联操作可以帮助解决--->也就是说当你操作主表时,自动的操作从表

    两种操作:

    1《 级联的删除

    ​ 当删除主表时自动删除从表中相关数据

    2《级联的更新

    ​ 当主表的主键更新时,会自动的更新关联从表的数据

    案例:

    create table if exists class;
    #如果这个表存在,创建新的表会产生重名的话,可以避免报错,if exists
    # if not exists 如果不存在才执行
    create table claaa(
    	id int primary key auto_increment,
    	name char(20),
    );
    insert into class values (null,'py9');
    insert into class values(null,'py10');
    
    #创建表的时候指定级联操作
    drop table if exists student;
    create table stydent(
    	id int primary key auto_increment,
    	name char(20),
    	gender char(1),
    	c_id int,
    	foreign key (c_id) references class(id)
        on update cascade
        on delete cascade
    );
    #级联操作可以单独使用 也可以一起使用,空格隔开即可
    insert into student values(null,"jack","m",1);
    insert into student values(null,"rose","m",1);
    insert into student values(null,"tom","m",2);
    

    外键的使用:

    ​ 什么时候时候外键:---------表之间存在关联关系

    首先确定表之间的关系

    1:多对一 (一对多)

    案例:部门==老师

    	#部门:
    	create table dept(
            id int primary key auto_increment,
            name char(20),
            job char(50),
            manager char(10)
    	);
    	#老师表:
    	create table teacher(
            id int primary key auto_increment,
            name char(20),
            gender char(1),
            dept_id int,
            foreign key(t_id) references teacher(id),
    	);
    

    2:多对多

    需要建立一个中间表

    学生 老师共同的id

    处理方式:

    ​ 建立一个中间表,用于存储关系,至少具备两个字段分别指向学生和老师的主键,两个字段都是外键 如下:

    create table t_s_r (
    id int primary key auto_increment,
    t_id int,
    s_id int,
    foreign key (t_id) references teacher (id),
    foreign key (s_id) references student(id),
    unique key (t_id,s_id)
    );
    #问题是  上表的id是可选的,如何保证没有重复关系
    
    1:
    #给两个字段设置联合唯一+非空
    alter table t_s_r add unique key(t_id,s_id);
    2:创建表时指定  多字段联合唯一
    alter table t_s_r(t_id int ,s_id int,unique key(t_id,s_id));
    
    
    #推荐 将中间的关系表  两个id作为联合主键同时具备了唯一且非空约束
    create table t_s_r (t_id, int s_id int,primary key(t_id,s_id));
    
    
    处理多对多关系
    1创建两个主表  如学员  和 老师
    2创建关系表  包含两个字段  分别设置外键 指向对应的表
    3将两个字段 作为联合主键
    

    案列:

    create table student(id int primary key auto_increment,name char(10));
    create table teacher(id int primary key auto_increment,name char(10)); 
    create table t_s_r(
        t_id int,
        s_id int,
        foreign key(t_id) references teacher(id),
        foreign key(s_id) references student(id),
        primary key(t_id,s_id)
        );
     # 先插入 学生或是老师都可以 但是关系表一定是最后添加的 
     insert into teacher values(null,"bgon"),(null,"nike");
     
      insert into student values(null,"老王"),(null,"老李");
      
      # 老王被bgon教过 
      insert into t_s_r values(1,1);
       # nike教过老李 
      insert into t_s_r values(2,2);
       # nike教过老王 
      insert into t_s_r values(2,1);
    
    
    
     已知老师名称为bgon 请找出他教过那些学生			
    1.通过名字获取 bgon的id 			
    2.拿着id取关系表中拿到一堆学生的id			
    3.通过学生的id取出学生的信息			
     select id from teacher where name = "bgon";
     select s_id from t_s_r where t_id = 1;
     select  * from student where id = 1;
     
     # 子查询方式   把一条语句的结果作为另一条语句的条件!
     select  * from student where id = (select s_id from t_s_r where t_id = (select id from teacher where name = "bgon"));
      
      
      
     已知学生名为老李 请查询出 哪些老师教过他  				
    1.通过名字获取老李的id
    select id from student where name = "老李";
    2.拿着id去关系表 找出老师的id				
    select t_id from t_s_r where s_id = 2;
    3.通过老师的id取出老师的信息 			
    select name from teacher where id = x;
    
    
    # 子查询方式:
    select name from teacher where id = (
        select t_id from t_s_r where s_id = (
            select id from student where name = "老李"
        )
    );
    

    3:一对一

    处理顺序:

    将先存在的数据作为主表

    后存在的作为从表

    使两个表的id保持一致 ---对应起来

    ​ 方法1:从表的id 即是主键 又是外键

    ​ 2:从表的id设置为外键 并保证唯一

    案列:

    #人员表
    create table person(
    	id int primary key auto_increment,
    	name char(10),
    	age int
    );
    #详情表
    create table person_info(
    	id int primary key,
    	heigent float,
    	weight float,
    	foreign key(id) references person(id)
    );
    #在这样的关系中,必须先插入主表即person,拿到id之后在添加详情表额数据
    #将一条完整数拆分到不同的表中,可以提高查询的效率,上述方法称之为垂直分表
    

    !@#¥%……***

    约束:精华

    unique 唯一
    not null 非空
    null 可以为空
    default 默认值
    primary key --->主键==(非空+唯一)加速查询
    auto_increment  自动增长‘
    foreign key   外键约束,保证两张表的关系是完整的
    级联操作 :用在外键关联中,可以级联的删除或更新从表记录
    
  • 相关阅读:
    NET5 WebApi 解决跨域问题
    CentOS7安装MYSQL
    VMWare安装CentOS7
    MSSQL还原数据库,更改用户登陆权限
    Vue自定义页面路由
    解决VSCODE"因为在此系统上禁止运行脚本"报错
    简析 HTTP 2.0 多路复用
    Git放弃本地修改,强制拉取最新版
    eclipse安装OpenExplorer插件--快速打开文件目录
    git统计某段时间内代码的修改量/总代码量
  • 原文地址:https://www.cnblogs.com/zhuyuanying123--/p/11178189.html
Copyright © 2011-2022 走看看