zoukankan      html  css  js  c++  java
  • 表的约束

    一:介绍

    约束条件与数据类型的宽度都一样,都是可选参数

    作用:用于保证数据的完整性和一致性

    null # 标识字段是否为可以为空
    not null  # 标识字段不能为空
    default # 为该字段设置默认值(null)
    
    primary key  # 标识此字段为该表的主键,可以唯一的标识记录
    foreign key #标识此字段为表的外键
    
    auto_increment # 标识该字段的值自动增长(只能用于主键)
    
    unsigned  # 无符号
    zerofill # 使用0填充
    

    二:null,not null,default

    1.null

    null:指定的字段是否为空,没有指定默认约束就是null

    上代码

    drop table test;
    create table test(name char(12));
    insert into test values();
    select * from test;
    insert into test values(null);
    select * from test;
    insert into test values(not null);
    select * from test
    
    
    2.not null
    指定的字段的值不为空

    上代码

    drop tables test;
    create table test(name char(15) not null);
    insert into test values();
    select * from test;
    insert into test values(null);
    select * from  test;
    insert into test values('hehe')
    select * from test;
    
    3.default

    default:被指定的字段在插入的值时无论如何null还是not null,都可以插入空,插入空默认填入default指定的默认值,注意,当已指定了约束条件not null时default后面就不能指定null作为默认值

    drop table test;
    create tabel test(name char(15) not null default 'hehe')
    insert into tset values();
    slect * from t1;
    insert into test values(null);
    select * from test;
    create table test(name char(15) not null default null);
    insert into test values();
    

    总结

    1. null是可以为空,values(),values(null),values('值')
    2. not null不能为空,values('值'),vlaues('not null')
    3. default当与not null连用.values不指定值会采用default后面的默认值,但是需要注意的是default后面这个时候不能指定null

    三:unique

    单列唯一:一个字段唯一

    联合唯一:多个字段联合以后唯一

    演示:单列唯一

    drop table test;
    create table test(id int unique,name varchar(16));
    insert into test values(1,'alen')
    insert into test values(1,'merlin') # 报错
    select * from test;
    insert into test values(2,'alen')
    select * from test;
    

    演示多列唯一

    ip和prot都可以重复,但是合到一起必须是唯一的
    
    drop table test;
    create tabel test(id int,host varchar(30),port varchar(10),unqiue(host,port));
    
    insert test values(1,'192.168.138.1','8080');
    insert test values(2,'192.168.138.15','8080');
    insert test values(3,'192.168.138.1','8080') # 报错
    select * from test;
    

    四:primary key

    1:键

    索引是mysql提供的专门数据结构,这种数据结构在mysql中称之为键,索引其实就是键

    2:主键

    一:单单从约束效果上来看primary key等价于not null + unique. 表示非空且唯一

    上代码

    drop table test;
    create table etst(id int primary key);
    insert into test values(null) # 报错
    insert into test values(1),(1) # 报错
    insert into test values(1),(2)
    select * from test;
    

    二:它除了有约束效果之外,它还是innodb存储引擎组织数据的依据,innodb存储引擎在创建表的时候必须要有primary key,因为它类似于书的目录,它能提升查询效率并且它也是建表的依据

    drop table test;
    create table test(
    	id int,
    	name varchar(16),
    	age int null unique,
    	addr varchar(32) not null unique);
    	
    desc test;
    

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

    drop table test;
    create table test(
    id int,
    name varchar(16),
    age int null unique,
    addr varchar(32) not null unique);
    desc test;
    

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

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

    单个字段主键

    create table test(id int primary key,
                     name varchar(16));
    

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

    create table test(host varchar(16),
                     port int,
                     primary key(host,port));
    
    总结

    以后建表必须指定只能有一个主键存在,通常是id字段被设置为主键

    为字段指定了了唯一的主键后,因为innodb存储引擎机制就是不为空且为一的字段,所以指定了主键就会默认相当默认执行你当前的字段不为空且唯一

    五:auto_increment

    一:自增介绍

    当编号特别多的时候,人为的去维护麻烦

    drop table test;
    
    create table test(id int primary key auto_increment,
                     name varchar(16));
    desc test;
    insert into test(name) values('eg'),('js'),('py'),('ke');
    select * from test;
    

    注意:auto_increment通常,都是加在主键上的不能给普通字段加

    drop table test;
    create table test(
        id int primary key auto_increment,
    	cid int auto_increment); # 报错
    
    二:总结
    1. 以后创建表的id(数据的唯一标识id,uid,sid)字段的时候就使用id int primary key auto_increment)
    2. auto_increment通常,都是加在主键上的不能被普通字段加

    三:补充

    1. 对于自增的字段,在用delete删除后,再插入值,该字段仍然按照删除前位置继续增长

      delete from

    2. 应该使用truncate清空表,比起delete一条一条地删除记录,truncate是直接清空表,在删除大表时用它(本质还是清空表,所以没有where等条件 truncate 表名

    四:了解知识:auto_increment修改及创建表时可以指定

    1. 在创建表后,修改自增字段的起始值

      alter table student auto_increment=3;
      
    2. 创建表时指定auto_increment的初始值.(注意初始值得设置为表选项,应该放到括号外)

      create table student(id int primary key
                          auto_increment,
                          name varchar(20),
                          sex enum('male','female') default 'male')
                          auto_increment = 3;
      

    六:foreign key

    强调:表类型必须是innodb存储引擎,且被关联字段,即references指定的另外一个表的字段,必须保证唯一

    一:定义一张员工表的三个缺点

    员工表:emp

    id name gender dep_name dep_desc
    1 red male 本部 扯犊子
    2 blune female 一部 吹牛
    3 green male 二部 喝酒
    4 yellow male 二部 喝酒
    5 orange female 三部 不良行为

    定义一张员工表,表中有很多字段,我们可以看出表上的三个缺点

    1. 该表的的组织结构不是很清晰
    2. 浪费硬盘空间
    3. 数据的扩展性极差
    二:优化表,将员工表拆分,
    id name gender
    1 red male
    2 blune female
    3 grenn male
    4 yellow male
    5 orange female

    部门表

    id name desc
    1 本部 扯犊子
    2 一部 吹牛
    3 二部 喝酒
    4 三部 不良行为
    三:外键foreign key介绍

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

    四:四种表的关系介绍
    1. 一对多关系
    2. 多对多关系
    3. 一对一关系
    4. 没有关系
    五:使用foreign key建立一对多的关系

    员工表

    id name gender dep_id
    1 red male 1
    2 blune female 2
    3 grenn male 3
    4 yellow male 3
    5 orange female 4

    部门表

    id name desc
    1 本部 扯犊子
    2 一部 吹牛
    3 二部 喝酒
    4 三部 不良行为
    # 先确定表与表之间的关系
    """
    先站在员工表考虑: 员工表里面的一个员工能否对应部门表里面的多个部门. --> 不能!!
        再站在部门表考虑: 部门表里面的一个部门能否对应员工表里面的多个员工. --> 可以!!
        结论: 员工表与部门表只是单向的一对多,那么员工表和部门表就是"一对多"的表关系.
    """
    
    """
    注意1: 一对多表关系   外键字段建在多的一方.  --> emp
    注意2: 在创建表的时候 一定要先建立被关联表.  -->  dep
    注意3: 在插入数据的时候 必须先往被关联表插值. --> dep
    
    # foreign key使用完整语法
        foreign key(关联表字段) references 表名(被关联表字段) on update cascade on delete cascade
    """
    
    # =================== 使用foreign key建立关联 ===================
    create table dep(
        id int primary key auto_increment,
        dep_name varchar(16),
        dep_desc varchar(32)
    );
    insert into dep(dep_name, dep_desc) values('外交部', '漂泊游荡'), ('教学部', '教书育人'), ('技术部', '技术能力有限部门');
    
    create table emp(
        id int primary key auto_increment,
        emp_name varchar(16),
        emp_gender enum('male', 'female'),
        dep_id int,
        foreign key(dep_id) references dep(id)
    );
    insert into emp(emp_name, emp_gender, dep_id) values('jason', 'male', 1), ('egon', 'female', 2), ('tank', 'male', 2), ('kevin', 'male', 2), ('oscar', 'female', 3);
    desc dep;
    desc emp;
    select * from dep;
    select * from emp;
    
    # 使用外键关联以后2表被外键关联的字段所对应的记录都不能进行更新. 员工表的: dep_id  部门部门表的: id
    update emp set dep_id=200 where dep_id=2;
    update dep set id=200 where id=2;
    
    # 使用外键的部门表不能进行记录的删除.
    delete from dep where id=2;
    delete from emp where id=2; # 员工表可以
    
    
    
    
    """删除的2种方式"""
    # 第一种: 先删除关联表(emp), 再删除被关联表(dep). 无论是争对记录的删除delete, 还是表的删除规则都是不变.
    delete from emp where id=1;
    delete from dep where id=1;
    
    # 第二种: 使用级联更新, 级联删除
    '''
    级联更新(同步更新) on update cascade
    级联删除(同步删除) on delete cascade
    '''
    drop table emp;
    drop table dep;
    create table dep(
        id int primary key auto_increment,
        dep_name varchar(16),
        dep_desc varchar(32)
    );
    insert into dep(dep_name, dep_desc) values('外交部', '漂泊游荡'), ('教学部', '教书育人'), ('技术部', '技术能力有限部门');
    
    create table emp(
        id int primary key auto_increment,
        emp_name varchar(16),
        emp_gender enum('male', 'female'),
        dep_id int,
        foreign key(dep_id) references dep(id)
        on update cascade  # 级联更新
        on delete cascade  # 级联删除
    );
    insert into emp(emp_name, emp_gender, dep_id) values('jason', 'male', 1), ('egon', 'female', 2), ('tank', 'male', 2), ('kevin', 'male', 2), ('oscar', 'female', 3);
    desc dep;
    desc emp;
    select * from dep;
    select * from emp;
    
    # 更新部门表的id. 员工表中得dep_id也会发生同样的改变
    update dep set id=200 where id=2;
    select * from dep;
    select * from emp;
    
    # 删除某一个部门表. 与部门表所关联的所有员工都会被清除.
    delete from dep where id=1;
    select * from dep;
    select * from emp;
    
    六:使用foreign key建立多对多关系

    注意: 争对多对多的表关系, 不能在两张原有的表中创建外键进行关联. 需要建立中间表来关联2表之间的关系.

    图书表book

    id titile price author_id
    1 python 100 1,2
    2 linux 250 1,2
    3 go 388 1
    4 js 88 2

    作者表

    id name age book_id
    1 老王 65 1,2
    2 隔壁芙蓉 18 3,4
    # 先确定表与表之间的关系
    """
    先站在书籍表考虑: 一本书可不可以有多个作者. --> 可以!!
        再站在作者表考虑: 一个作者可不可以写多本书. --> 可以!!
        结论: 书籍表和作者表是双向的多对多, 那么表关系就是"多对多"关系.
    """
    
    create table book(
        id int primary key auto_increment,
        title varchar(32),
        price int,
        author_id int,
        foreign key(autor_id) references author(id)
        on update cascade  # 级联更新
        on delete cascade  # 级联删除
    );
    
    create table author(
        id int primary key auto_increment,
        title varchar(32),
        age int,
        book_id int,
        foreign key(book_id) references book(id)
        on update cascade  # 级联更新
        on delete cascade  # 级联删除
    );
    
    """按照上述的方式创建 一个都别想成功!!"""
    

    中间表:book2autho

    注意1: 如果一本书有多个作者必须重新开启一行.

    注意2: 建立了中间表以后中间表与上面2表是多对一的关系. 新建的中间表是多的一方, 上面2表是一的一方. 所以因该先创建上面2表, 再创建需要建立外键关联中间表

    一个book2author中的id可以对应多个作者. --> 不成立

    一个作者可以对应多个book2author中的多个id --> 成立

    id book_id author_id
    1 1 1
    2 1 2
    3 2 1
    4 2 2
    5 3 3
    6 4 1
    create table book(
        id int primary key auto_increment,
        title varchar(16) not null,
        price int not null
    );
    insert into book(title, price) values('python', 100), ('linux', 250), ('go', 388), ('js', 88);
    
    create table author(
        id int primary key auto_increment,
        name varchar(16) not null,
        age int not null
    );
    insert into author(name, age) values('老王', 18), ('隔壁芙蓉', 78);
    
    
    # 针对多对多字段表关系 不能在两张原有的表中创建外键 需要你单独再开设一张 专门用来存储两张表数据之间的关系
    create table book2author(
        id int primary key auto_increment,
        book_id int not null,
        author_id int not null,
        foreign key(book_id) references book(id)
        on update cascade   # 级联更新
        on delete cascade,  # 级联删除
        foreign key(author_id) references author(id)
        on update cascade  # 级联更新
        on delete cascade  # 级联删除
    );
    insert into  book2author(book_id, author_id) values(1, 1), (1, 2), (2, 1), (2, 2), (2, 2), (3, 2), (4, 1);
    
    select * from book;
    select * from author;
    select * from book2author;
    
    七:使用foreign key 建立一对一关系

    作者表author

    注意: 对于一对一关系表authordetail_id使用过就不能使用, 应该在外键的基础之上使用unique

    id name age authordetail_Id
    1 老王 65 1
    2 隔壁芙蓉 18 2

    作者详情表:authordetail

    id postcode addres
    1 335000 鹿儿岛
    2 20050 九州
    # 先确定表与表之间的关系
    """
    站在作者的角度:
        一个作者可以对象多个用户详情. --> 不成立
    站在详情的角度:
        一个用户详情可以对应多个作者. --> 不成立
    结论: 一对一    
    """
    # 强调!!!: 外键字段建在任意一方都可以 但是推荐你建在查询频率比较高的表中(author)
    
    create table authordetail(
        id int primary key auto_increment,
        postcode int not null,
        address varchar(64) not null
    );
    insert into authordetail(postcode, address) values(335000, '鹿儿岛'), (200050, '九州市');
    
    create table author(
        id int primary key auto_increment,
        name varchar(16) not null,
        age int not null,
        authordetail_id int not null unique,  # 注意: 对于一对一关系表authordetail_id使用过就不能使用, 应该在外键的基础之上使用unique.
        foreign key(authordetail_id) references authordetail(id) 
        on update cascade
        on delete cascade  
    );
    insert into author(name, age, authordetail_id) values('老王', 65, 1), ('隔壁芙蓉', 18, 2);
    
    select * from author;
    select * from authordetail;
    
    八:总结
    1. 表关系的建立需要用到foreign key

      1. 一对多,外键字段建立在多的一方
      2. 多对多,开设中间表存储
      3. 一对一,外键字段建立在任意一方都可以,但是推荐建立在查询频率比较高的一方
    2. 判断表之间关系的方式

      1. 从多个角度切入,如果是2表之间的关系那么只有在2表之间都换位思考以后,才能进行判断表与表之间的关系
    3. 使用

      foreign key(关联表字段) references 被关联表表名(被关联字段) 
      on update cascade 级联更新(同步更新)
      on delete cascade 级联删除(同步删除)
      
  • 相关阅读:
    [置顶] 算法设计基础
    .net 多线程学习
    如何获得Repeater中的列
    npoi导出excel
    字符串的格式化问题
    用线程修改页面中的值(一)
    正则表达式的验证数值验证
    .net 线程更新页面中的值(方法二)
    .net 线程更新页面中的值(方法一)
    字符串的分割
  • 原文地址:https://www.cnblogs.com/wait59/p/13633897.html
Copyright © 2011-2022 走看看