zoukankan      html  css  js  c++  java
  • 数据库 级联,约束,外键

    数据库 级联 约束 外键

    小练习:创建博客表

    标题 发布时间 最后更新 作者 内容 字数

    char(100) datetime timestamp char(100) longtext bigint

    create table blog(
        title char(100),
        publish_time datetime,
        last_update  timestamp,
        author char(100),
        content longtext,
        number bigint
    );
    
    insert into blog values(
        "mysql 高级篇",
        now(),
        null,
        "jerry 夫斯基",
        "啥也不说了 就是很高级",
        11);
    
    select title from  blog where number = 100;
    
    上节课内容回顾
    
    1.简单的增删改查语句
    
    insert into table_name values(v1,v2,...);
    insert into table_name(column1,column2) values(v1,v2,...);
    insert into table_name values(v1,...) ,(v1,....);
    
    delete from table_name where 条件;
    
    update table_name set column = new_valuem,... where 条件;
    
    select * from table_name;
    select column1,... from table_name where 条件;
    

    2.数据类型

    1.整形
    tyniint smallint mediumint int bigint
    
    2.浮点
    float double decimal
    
    3.字符串
    char varchar   tiny | long [text blob]  binary  varbinary
    
    枚举   enum
    
    集合  set
    
    4.日期和时间
    date  time datetime  year  timestamp
    

    什么是约束 constraint

    约束就是一种限制,例如宪法,让你不能做某些事情
    
    ​数据库的约束,是对数据的安全性,完整性的保证;
    

    mysql中的约束

    关键字 作用描述 举例
    unique 唯一性约束,表示这个字段不能出现重复的值, 用于唯一标识一条记录 例如身份证号码,学号等
    not null 非空约束,表示这个字段的值不能为空 例如姓名,密码
    null 一些数据类型默认就是可以为空的
    default 默认值,用于给某一个字段设置默认值 gender enum("g","b") default "b"

    普通约束测试

    
    #完整的建表语句
    create table table_name(字段名称 字段类型[(宽度) 约束]) charset utf8;
    
    #学生表 具备  姓名 性别 学号
    create table student(
        #非空
        name char(20) 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,"tom"); # Column 'id' cannot be null #主键不能为空  
    
    #从约束角度来看就等同于,非空+唯一  
    create table person2(
        id char(19),
        name char(20)
    );
    
    # 在innodb存储引擎中 ,主键用于组织数据 (树形结构)  
    # 也就说主键对于innodb引擎来说是必须要的,没有不行!
    # 如果没有手动指定主键  
    # mysql 会自动查找一个具备非空且唯一的字段作为主键
    # 如果也没有也没有这样的字段,mysql会创建一个隐藏字段 作为主键
    # 首先明确主键是一种索引  unique也是,索引的作用是加速查询  
    # 如果我们在查询语句中没有使用索引字段 ,mysql将无法为我们的查询加速 意味着如果没有主键,将无法加速查询
    
    总的来说:主键 具备约束的作用,还能加快我们的查询速度,所以今后在创建表的时候都应该创建索引字段
    应该将什么样的字段设置为主键????
    如果本来的业务中就存在非空且唯一的字段 那就把它设为主键   如果没有就自己添加一个字段专门作为主键  
    通常我们会将主键设置为类int 类型,是为了方便保证其唯一;
    
    案例:
    mysql> create table PC(
        id int primary key,
        pp 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");# 也可以跳过这个字段
    
    create table teacher3(
        id char unique auto_increment ,
        name char(10)
    );
    
    自动增长可以用在 具备索引,并且是数字类型的字段上,但是通常与主键一起使用!
    

    表之间的关系

    表之间的关系
    

    foreign_key

    外键约束,用于指向另一个表的主键字段  
    
    # 创建表的时候添加外键
    create table teacher(
        id int primary key auto_increment,
        name char(20),
        gender char(1),
        dept_id int,
        foreign key(dept_id) references dept(id)
    );
    
    解释:
    foreign 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
    
    ​delete from dept where id = 1;# 报错
    
    ​必须先删除从表 再删除主表
    
    ​delete from teacher where dept_id = 1;
    ​delete from dept where id = 1;
    
    
    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.级联更新

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

    案例:以上面的班级个学员为例:

    drop table if exists class;
    # 如果这表存在 才执行删除  可以避免报错  if exists
    # if not exists  如果不存在才执行
    create table class(
        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 student(
        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);
    

    外键的使用

    什么时候使用外键:
    ​表之间存在关联关系 ,
    首先要确定表之间的关系:
    

    多对一

    ​一对多(多对一)

    1562916076988
    或者

    1562916076988

    老师和部门的关系
    老师的角度看
    一个老师应该对应有一个部门
    一个老师可以对应对多个部门?  不行 一个老师只能属于一个部门 (要看具体业务要求)!
    多个老师可以对应一个部门
    多对一
    部门的角度看
    一个部门可以对应多个老师
    一个部门可以对应一个老师
    多个部门可以对应一个老师? 不行
    一对多
    如何处理一对多(多对一)?
    在老师表中存储 部门id
    即多的一方存储 一的一方的id
    

    处理方式

    ​在一的一方即teacher表中保存相应部门(多的一方)的编号
    案例:

    #部门:
    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

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

    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);
     # 创建表时指定 多字段联合唯一
     create table t_s_r2(t_id int,s_id int,unique key(t_id,s_id));
    
     方式2:
     # 推荐 将中间的关系表 两个id 作为联合主键 同时具备了 唯一且非空约束
     create table t_s_r3(t_id int,s_id int,primary key(t_id,s_id));
    
    处理多对多关系
    1.创建两个主表  如学员 和 老师
    2.创建关系表 包含两个字段 分别设置外键 指向对应的表
    3.将两个字段 作为联合主键  
    
    

    案例

    1562916076988

    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 = "老李"
        )
    );
    

    一对一关系

    ​如一个客户对应一个学生:
    ​站在两边看都是一对一的关系
    

    处理方式三

    ​确定先后顺序
    ​将先存在的数据作为主表
    ​后存在的作为从表
    ​使两个表的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,
        height float,
        weight float,
        foreign key(id) references person(id)
    );
    #再这样的关系中 必须先插入主表即person 拿到一个id 在添加详情表的数据  
    #将一条完整数拆分到不同表中,可以提高查询的效率,上述方式称之为垂直分表!
    
    
    约束:
    
    unique   唯一
    not null   非空
    null 可以为空
    default    默认值
    primary key   主键 ==(非空+唯一+加速查询)
    ​auto_increment    自动增长
    foreign key    外键约束 , 保证两张表的关系是完整的
    ​级联操作: 用在外键关联中,可以级联的删除或更新从表记录  
    
  • 相关阅读:
    H: Dave的组合数组(二分法)
    G: Dave的时空迷阵(next数组)
    计蒜客 X的平方根(二分法)
    最短路径四种方法
    POJ 2001 Shortest Prefixes(字典树活用)
    HDU 1671 Phone List (qsort字符串排序与strncmp的使用 /字典树)
    快速排序原理
    抓捕盗窃犯
    Hash函数
    Monkey King(左偏树 可并堆)
  • 原文地址:https://www.cnblogs.com/bladecheng/p/11178245.html
Copyright © 2011-2022 走看看