MySQL表的约束

MySQL表的约束

  • 一.表的约束的概念
  • 二.表的非空约束
    • 1.NULL与' '比较
    • 2.空属性null
  • 三.默认值default
  • 四.列描述comment
  • 五.zerofill
  • 六.主键primary key
    • 1.唯一主键
    • 2.复合主键
    • 3.自增长auto_increment
  • 七.唯一键
  • 八.外键
  • 九.综合案例

一.表的约束的概念

真正约束字段的是数据类型,但是数据类型约束很单一,需要有一些额外的约束,更好的保证数据的合法性,从业务逻辑角度保证数据的正确性。所谓约束,就是避免犯一些低级错误,比如类似于语法错误,编译器的编译失败实际上也算是一种约束。

表中一定要有各种约束,通过约束,让我们未来插入数据库表中的数据是符合预期的。

约束的本质: 通过技术手段倒逼程序员插入正确的数据。反过来站在mysql的视角,凡是插入进来的数据,都是符合数据约束的。

约束的最终目标: 保证数据的完整性和可预期性。

为什么数据库这么严格?

数据库作为维护用户数据的最后一道防线,必须要保证数据库的数据是满足预期的,因此数据库的约束必须严格。为了更好的约束,就需要更多的约束条件,这也是这一节的内容。

通过desc操作,其后四列就属于约束条件:

image-20230723210341424

总结一下:约束就是表结构的设计者在其他人插入数据之前,预先把规则定好,再让被别人按照他的规则进行数据的增删查改,不满足约束的数据不会被插入到对应的表中,这样下来,插入后的数据就是完整的,并且是可预期的。

表的约束很多,这里主要介绍如下几个: null/not null,default, comment, zerofillprimary keyauto_incrementunique key

二.表的非空约束

1.NULL与’ '比较

在MySQL数据类型已经说过,这二者是不同的,NULL代表什么都没有,而' '代表一个空串。

在select语句中,NULL不会参与到相应的计算操作中。

MySQL表的约束_第1张图片

2.空属性null

在这个约束中,有两个选择:

  • null(默认的)
  • not null(不为空)

数据库默认字段基本都是字段允许为空,但是实际开发时,尽可能保证字段不为空,因为数据为空没办法参与运算。因此要添加非空约束,不让其中一个属性为空时插入。

创建表时约束不为空:not null

create table myclass(
    class_name varchar(20) not null,
    class_room varchar(20) not null,
    other varchar(20)
);

MySQL表的约束_第2张图片

这样,在NULL列中就会发现显示的是No,也就是不允许为空,即我们插入数据时,代表No的两行必须插入有效数据,否则就无法插入。

MySQL表的约束_第3张图片

三.默认值default

实际上就是缺省值,建表时设定之后,即便不对这个字段进行插入,其对应的值也会默认为default后面跟着的值。

MySQL表的约束_第4张图片

插入default对应的字段后,就会将缺省值覆盖。

MySQL表的约束_第5张图片

实际上,default就是在创建表之前将缺省值也插入进去。如果not null和default同时设置,not null的限制也会被default的缺省值补齐,因此并不是真的不插入,而是插入了缺省值。

MySQL表的约束_第6张图片

我们在没有default约束,也没用not null约束时,是允许为空的,这个null值实际上却是mysqld底层优化出来的default的缺省值。

MySQL表的约束_第7张图片

四.列描述comment

实际上comment描述的设置并不会阻止数据进行插入,其可以等同于注释,即对列的介绍。

MySQL表的约束_第8张图片

那为什么还说comment是一种约束呢?实际上什么都约束不了啊?

其实,通过程序员的插入数据,comment会对思想上做出约束,告诉你这是一种什么数据。也算是一种软约束。

五.zerofill

zerofill约束,就是补位。对于我们所创建的表,会发现在一个整形数据类型中带有括号字段。

MySQL表的约束_第9张图片

而这个字段就代表着整形int的数据的最大长度,一般的数据达不到这样的长度,那么如果使用zerofill约束,就会用0将没用到的位置进行占位。

MySQL表的约束_第10张图片

插入数据:

MySQL表的约束_第11张图片

可以看出二者的区别。

六.主键primary key

索引和主键之间是有联系的。

主键:primary key用来唯一的约束该字段里面的数据,不能重复,不能为空,一张表中最多只能有一个。

主键;主键所在的列通常是整数类型,比如学号,编号等具有唯一性质的数据。

1.唯一主键

  • 创建表时约束某一字段为主键。

MySQL表的约束_第12张图片

为了保证不能重复,不能为空,相应的创建语句在mysqld中也会添加not null,Key也会标记PRI保证不能重复。

  • 删除主键约束

MySQL表的约束_第13张图片

这样,插入的数据就可以重复,但是通过观察,仍不能为空,因为not null在创建表时的添加约束期间会一并添加到约束。不过有了主键,才能更好的查找数据,因为其具有唯一性。

  • 已经建好的表对指定字段添加primary key约束

MySQL表的约束_第14张图片

需要注意的是,添加primary key的字段,里面已经插入的数据不能存在重复值,否则就会违背主键的概念,导致约束添加失败。因此,为了避免这种情况,最好在创建表时一并添加主键约束。

2.复合主键

回到上述定义,一张表中最多只能有一个主键,但这并不意味着一个表中的主键只能添加到一列。一个主键也可以被添加到多列上,此时的主键被称为复合主键。

两个或者多个字段一并添加为主键,采用如下方式:

MySQL表的约束_第15张图片

这就将id, course_id同时设置为主键,这两个字段就成为复合主键。即这两个字段只要不同时相同,那么就是唯一的。

验证

MySQL表的约束_第16张图片

只要二个字段不是都相同,就可以进行插入,因为确定唯一性的字段有两个。

3.自增长auto_increment

自增长也算主键的一种。将其设置为主键,就不用继续管它,插入数据时它本身会为了防止重复而自增+1。看看定义是怎么给的

auto_increment:当对应的字段,不给值,会自动的被系统触发,系统会从当前字段中已经有的最大值+1操作,得到一个新的不同的值。通常和主键搭配使用,作为逻辑主键。

自增长的特点

  • 任何一个字段要做自增长,前提是本身是一个索引(key一栏有值)
  • 自增长字段必须是整数
  • 一张表最多只能有一个自增长

MySQL表的约束_第17张图片

那么此时,即便是主键的id,我们也可以不用理会,直接插入name字段也不会发生错误:

MySQL表的约束_第18张图片

当然,就如同缺省值default一样,这个由于主键的唯一性多了一个自增的条,因此id也可以插入指定的数字:

MySQL表的约束_第19张图片

如果继续插入,不理会id,那么它就会从1000开始自增,下一个就是1001:

MySQL表的约束_第20张图片

为什么能够接着自定义的数据继续自增计数呢?

这是由于在表结构内部存在一个能够存储下一个id值的值,当下一条数据插入,就会将这个值赋值给新的数据对应的id字段:

MySQL表的约束_第21张图片

而我们手动插入的值,实际上就会更改这个值,即将手动的值+1保存到此位置。因此,在建表时,我们也可以手动设置这个值:

MySQL表的约束_第22张图片

通过last_insert_id函数,可以获取上一次的AUTO_INCREMENT的值:

select last_insert_id();

七.唯一键

唯一键:唯一键约束后,该字段也具备了和主键一样的唯一性。唯一键允许为空,而且可以多个为空,因为空字段不做唯一性比较。

唯一键和主键的区别:

  • 在使用中,主键是标识唯一性,而唯一键是保证业务中的数据唯一性。
  • 主键一个表只能有一个,唯一键可以有多个。
  • 主键不能为空,唯一键可以为空,甚至多个为空。

对于主键的标识唯一性以及唯一键的业务唯一性的理解:

一个表中若存在id,name,telephone三个字段,无疑id是要被标识唯一性主键的。在插入数据中,telephone作为业务上的数据,不能出现重复,一旦插入出现纰漏,将相同的telephone的数据给了不同的id,那么就造成了无法精准确定个人信息的情况,为了避免这种情况的发生,就需要将telephone进行唯一性约束

唯一性约束语法:unique

create table student(
    id char(10) primary key '学生的id',
    name varchar(20) comment '学生的名字',
    telephone varchar(11) unique comment '电话号具有唯一性'
);

MySQL表的约束_第23张图片

八.外键

对于学生表和班级表,学生一定隶属于某一个班级,因此两个表之间一定存在所属关系,学生属于班级,设计表时通过外键约束学生就属于从表,班级就属于主表。

如果将学生表和班级表结合成一个表,那么在插入数据时,就需要插入大量的字段造成没必要的冗余。若将其分成两个表,那么通过一一对应的映射,来减少没必要的数据。

为什么会造成没必要的冗余?

假设学生表有三个字段,班级表有两个字段(其中有一个为公共属性)。在两个表的前提下,若要新增一名学生信息,只需要插入三个字段;若合并成一个表,那么就需要插入3+2-1=4个字段,并且我们知道组合起来的情况也会更多,两个表合并的结果就是数据位置上的相乘,比如:

两个表MySQL表的约束_第24张图片

合并成一个表

MySQL表的约束_第25张图片

张三,李四的数据都分别出现了两次,所以一个表会产生数据冗余。

外键是用于定义主表和从表之间的关系

外键约束主要定义在从表上,主表则必须是有主键约束或unique约束。当定义外键后,要求外键列数据必须在主表的主键列存在或为null。

语法:

foreign key(字段名) references 主表()

实例

创建两个表,student和class

MySQL表的约束_第26张图片

插入对应信息

MySQL表的约束_第27张图片

上面插入的都是符合逻辑正常的插入。

如果在学生表中插入class_id=3的学生,虽然可以插入,但是class表中并没有对应的班级;如果操作delete from class where id=1;让通信101班级不存在,但学生表仍有通信101对应id的学生。因此,这就需要让两个表产生联动,插入class_id=3的学生的前提是存在id=3的班级,删除id=1的班级最后会连着学生表中所属class_id=1的学生信息一并删除,这就涉及到了外键的约束。

外键存在两种关系:

  1. 关联关系:逻辑上的关系,表与表之间有相同字段。
  2. 约束关系:通过关联关系实现表之间的约束。

此时student中的class_id存在外键之名(关联关系),但是没有外键之实。

所以,我们需要重新建立一个从表student,目的是引入外键的逻辑关系。

MySQL表的约束_第28张图片

目前的学生表是空的,先插入数据:

MySQL表的约束_第29张图片

若删除id=1的班级,也不会成功,因为student中还存在class_id=1的学生。只有在student中不存在id=1的学生,才能删除。

image-20230726173349925
这就叫做外键约束。外键的本质就是产生关联,增加约束,保证表和表之间的完整性。
注:主表在从表存在的前提下,不能drop table 主表。


外键约束中,也存在constraint将外键约束命名,不过mysqld内部会自动做这样的操作。

MySQL表的约束_第30张图片

九.综合案例

有一个商店的数据,记录客户及购物情况,有以下三个表组成:

  • 商品goods(商品编号goods_id,商品名goods_name, 单价unitprice, 商品类别category, 供应商provider)
  • 客户customer(客户号customer_id,姓名name,住址address,邮箱email,性别sex,身份证card_id)
  • 购买purchase(购买订单号order_id,客户号customer_id,商品号goods_id,购买数量nums)

要求:

  • 每个表的主外键
  • 客户的姓名不能为空值
  • 邮箱不能重复
  • 客户的性别(男,女)

SQL操作:

-- 创建数据库
create database if not exists cfy_database
default character set utf8;

-- 选择数据库
use cfy_database;

-- 创建数据库表
-- 商品
create table if not exists goods
(
 goods_id  int primary key auto_increment comment '商品编号',
 goods_name varchar(32) not null comment '商品名称',
 unitprice  int  not null default 0 comment '单价,单位分',
 category  varchar(12) comment '商品分类',
 provider  varchar(64) not null comment '供应商名称'
);


-- 客户
create table if not exists customer
(
 customer_id  int primary key auto_increment comment '客户编号',
 name varchar(32) not null comment '客户姓名',
 address  varchar(256) comment '客户地址',
 email  varchar(64) unique key comment '电子邮箱',
 sex  enum('男','女') not null comment '性别',
 card_id char(18) unique key comment '身份证'
);


-- 购买
create table if not exists purchase
(
 order_id  int primary key auto_increment comment '订单号',
 customer_id int comment '客户编号',
 goods_id  int comment '商品编号',
 nums  int default 0 comment '购买数量',
 foreign key (customer_id) references customer(customer_id),
 foreign key (goods_id) references goods(goods_id)
); 

你可能感兴趣的:(MySQL,mysql,android,数据库)