【MYSQL】-表的约束

在这里插入图片描述
💖作者:小树苗渴望变成参天大树🎈
🎉作者宣言:认真写好每一篇博客💤
🎊作者gitee:gitee✨
💞作者专栏:C语言,数据结构初阶,Linux,C++ 动态规划算法🎄
如 果 你 喜 欢 作 者 的 文 章 ,就 给 作 者 点 点 关 注 吧!

文章目录

  • 前言
  • 一、空属性
  • 二、默认值
  • 三、列描述(comment)
  • 四、zerofill
  • 五、主键(primary key)
  • 六、唯一键(unique key)
  • 七、自增长(auto_increment)
  • 八、外键(foreign key)
  • 九、案例
  • 十、总结


前言

今天我们开始讲解表的约束,对于约束上一篇已经提到过了,目的就是让插入表的数据更加的符合我们的预期,我们单单使用数据类型进行约束时远远不够的,例如,姓名和爱好,都设置成varchar类型,那就会出现将爱好插入到姓名的可能,这样就造成数据错乱的问题,所以我们还需要更多的约束去让我们程序员规范的插入数据。真正约束字段的是数据类型,但是数据类型约束很单一,需要有一些额外的约束,更好的保证数据的合法性,从业务逻辑角度保证数据的正确性。比如有一个字段是email,要求是唯一的 表的约束很多,这里主要介绍如下几个: null/not null,default, comment, zerofill,primarykey,auto_increment,unique key


为什么我们sql要这么严格规范插入数据的合理合法性呢??
原因是数据库是维护用户数据的最后一道防线,对于一些个人信息,财产的数据,出现错误就不是小错误了,所以sql要非常严格,不仅仅对程序员要严格,也是为了严格的保护用户数据

一、空属性

两个值:null(默认的)和not null(不为空)
数据库默认字段基本都是字段为空,但是实际开发时,尽可能保证字段不为空,因为数据为空没办
法参与运算。
在这里插入图片描述

sql里面的null不代表0就表示什么都没有,null和‘’‘’是不一样的,一个是什么内容都没有,另一个是有内容表示的是空串。

案例:
创建一个班级表,包含班级名和班级所在的教室。
站在正常的业务逻辑中:

  1. 如果班级没有名字,你不知道你在哪个班级
  2. 如果教室名字可以为空,就不知道在哪上课

所以我们在设计数据库表的时候,一定要在表中进行限制,满足上面条件的数据就不能插入到表中。这就是“约束”。

//直接在数据类型后面加上约束条件就可以了	
create table myclass(
class_name varchar(20) not null,
class_room varchar(10) not null);

在这里插入图片描述
我们插入数据:
在这里插入图片描述

我们看到前两次插入可以插进去可以理解,前两个属性没有为空,第三个属性可以为空,后面两个属性插入失败也可以理解,第二个属性你不插入数据或者插入null都是不符合约束的,但是错误信息不一样,这是为什么??,一会解释

上面的约束还有一个小问题要解决,我们先来学习完下面的这一个属性。

二、默认值

默认值:某一种数据会经常性的出现某个具体的值,可以在一开始就指定好,在需要真实数据的时候,用户可以选择性的使用默认值。

create table tt10 (
name varchar(20) not null,
age tinyint unsigned default 0,
sex char(2) default '男'
);

在这里插入图片描述
我们插入数据看看:
在这里插入图片描述

我们看到将设置成有默认值的属性插入数据,就是要我们插入的,没有插入才是要默认的。


接下来用一张表带大家在来了解一下空属性和默认值。

create table test(
name varchar(20),
age tinyint default 18,
gerder char(2) not null default '男');

在这里插入图片描述

有默认值的列,在插入值的时候可以对列进行省略,只有默认值,插入null也是可以的,因为没有notnull进行约束。


我们再来看一张表:

create table test1(
name,varchar(20),
age tinyint);

在这里插入图片描述

这是一张没有约束的表,我们将age列省略了,我这创建表的时候也没有设置默认值,按照上面的数据,只有设置了默认值的列在插入的时候才可以省略,那应该会报错,但是结果是插入成功了,原因是sql是进行优化,你没有设置notnull,sql就会给你设置一个默认值为null,如果你设置了notnull,那么sql就不会给你生成默认值了。这个大家下去在测试一下。

大家完全不用担心,因为not null一般不和默认值一起设置,你设置了默认值,就意味着不为空,但是sql语法支持这样一起设置,我们后面使用的时候一般设置一个就可以了,大概率不会一起设置的。

大家对于第一节的问题有没有答案了呢,第一个省略了没有默认值的列,所以会报没有默认值的错误,第二个有notnull你插入null会肯定先报notnull的错误。

三、列描述(comment)

列描述:comment,没有实际含义,专门用来描述字段,会根据表创建语句保存,用来给程序员或DBA来进行了解。
在这里插入图片描述

这个是方便我们管理员查看你插入的数据和描述的内容是不是一样的,也方便管理员知道每一列表达的含义是什么,才能更好的管理数据。

四、zerofill

刚开始学习数据库时,很多人对数字类型后面的长度很迷茫。
我们创建一个表:

create table test3(
a int unsigned,
b int);

在这里插入图片描述
可以看到int(10),int(11)这个代表什么意思呢?整型不是4字节码?这个10又代表什么呢?其实没有zerofill这个属性,括号内的数字是毫无意义的。a和b列就是前面插入的数据,如下:
在这里插入图片描述
但是对列添加了zerofill属性后,显示的结果就有所不同了。修改tt3表的属性:

alter table test3 modify a int zerofill;

在这里插入图片描述
在这里插入图片描述

这次可以看到a的值由原来的1变成0000000001,这就是zerofill属性的作用,如果宽度小于设定的宽度(这里设置的是10),自动填充0。要注意的是,这只是最后显示的结果,在MySQL中实际存储的还是1。为什么是这样呢?我们可以用hex函数来证明:
在这里插入图片描述

我们再来修改一下属性,将int后面的数字改小点:
在这里插入图片描述

我们看到不够设置的数字大小就补0,超过了,是多少就是多少,是至少的行为。也算是一种格式化输出的形式。

为什么有这个设计:原因有的场景需要,它需要插入的数据长度是一样的,显示效果好,比如班级的显示,都是固定长度

为什么我们的int默认后面的数字是11,unsigned int 默认的是10,大家都知道我们int的范围不论是在有符号还是无符号都是21亿或者是42亿,这些数字最大也只占10为,有符号的多一位了是因为要显示负号

五、主键(primary key)

主键:primary key用来唯一的约束该字段里面的数据,不能重复,不能为空,一张表中最多只能有一个主键;主键所在的列通常是整数类型 ,主键的作用是方便去查询
案例:

  1. 创建表的时候直接在字段上指定主键
create table tt13 (
id int unsigned primary key comment '学号不能为空',
name varchar(20) not null);

在这里插入图片描述
被设置为主键的列自动加上notnull。并且默认值为NULL,所以插入的时候必须要有数据。不能省略行。

  1. 主键约束:主键对应的字段中不能重复,一旦重复,操作失败
insert into tt13 values(1, 'aaa');//插入两次

在这里插入图片描述

  1. 删除主键
    我们的主键是唯一的,所以不需要指定列去删除主键
alter table tt13 drop primary key;

在这里插入图片描述

可以去掉主键,但是空属性还是不变,我们发现去掉主键可以插入重复的数据了。

  1. 当表创建好以后但是没有主键的时候,可以再次追加主键
alter table tt13 add aprimary key(id);

在这里插入图片描述

我们的id里面有相同的数据,所以设置成主键就会出现错误,所以要删除,那我们也不知道删除那一个,都有可能造成数据的损失,所以主键一般不要再中途加,创建表的时候就设置好。

  1. 复合主键
    我们最开始就说过再一张表中主键只能有一个,但是不意味着主键只能是一个属性,我们可以设置多个属性当成主键。
    例子:我们学生选一门课只能选一次,所以我们再表中要使学生的学号和课程号两个不能有重复,但是一个学生可以选多门课,这门课也可以被多个学生选,所以我们将学号和课程号作为复合主键。
create table tt14(
id int unsigned comment'学号',
course char(10) comment'课程号',
primary key(id,course));//id和course为符合主键,一个属性为主键的时候也可以这样写。

在这里插入图片描述

通过查看表结构来看,我们的两个属性都不准为空,而且都有默认值,id的默认值是0,course的默认值是空格,它不是表示NULL。

我们插入数据看看:
在这里插入图片描述

通过上面的测试我们知道符合主键的特点了,它不能为空,并且有自己的默认值,所以插入的时候对应的列可以省略,和单个属性是主键有差别,它不能为空,但是默认值为NULL,所以它插入的时候必须要插入数据,不能使用默认值。这个大家要清楚。

注意:我们发现除了单个属性作为主键可以控制此属性是唯一的,而复合主键不行,保证不了任何一个属性的唯一性,万一此表有多列属性需要唯一性去约束怎么办??此时有了一个新的约束叫做唯一键。

六、唯一键(unique key)

我们在入学的时候,老师们需要录取我们的信息,我们都知道学号是标识我们每个人的,所以学号是唯一的,我么需要将他设置成主键,但是每个人的手机号也是唯一的,此时不能再设置一个主键了,所以我们需要将电话号设置成唯一键,来保证它的唯一性。
案例:

create  table tt15(
id int unsigned,
name varchar(20) not null,
telphone char(11) unique key,
primary key(id));

在这里插入图片描述

我们看到表结构第三行是唯一键,但是它可以为空,这是它和主键的区别,如果将主键写在属性后面就没有默认值,写在最后就会有默认值。

插入数据:
在这里插入图片描述

理解主键和唯一键:
我们的一张表中可能有多个属性需要保证它的唯一性,通过第五节的测试来看,主键不能没有这样的功能,所以唯一键是必须的,其次单个属性表示的主键是由唯一性的,所以主键是从多个具有唯一性的属性中挑出来的,也可以选择其他具有唯一性的属性列。这是选择的问题。两者的本质是:主键不能为空,唯一键可以为空,空字段不做唯一性比较。两者的区别是:我们可以简单理解成,主键更多的是标识唯一性的。而唯一键更多的是保证在业务上,不要和别的信息出现重复,但一个唯一键设置了非空,其实你也可以将他当成主键。

七、自增长(auto_increment)

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

  1. 任何一个字段要做自增长,前提是本身是一个索引(key一栏有值)
  2. 自增长字段必须是整数
  3. 一张表最多只能有一个自增长
create table tt16(
id int unsigned primary key auto_increment,
name varchar(20) not null);

在这里插入图片描述

我们设置了自增长的属性,再插入的时候可以不用管,但是你要插入也是可以的。

插入数据:
在这里插入图片描述

我们看到默认值从1开始的,如果自己插入了数据就按照自己插入的算,下次自增长从上行的数据开始增加。

怎么设置默认值:
在这里插入图片描述

我们看到由变量记录下次自增长的数字是多少,所以我们再创建表的时候设置初始值就可以了。

在这里插入图片描述

如果你插入了id是1,2,3,但是你删除了2这一行数据,下次插入只会从插入4,不会插入2,除非你指定。

八、外键(foreign key)

外键用于定义主表和从表之间的关系外键约束主要定义在从表上,主表则必须是有主键约束或unique约束。当定义外键后,要求外键列数据必须在主表的主键列存在或为null
在这里插入图片描述
假设c++大牛班有100人,java大神班有120人,如果再一张表中,那么班级这一列就会出现数据冗余,所以需要把表进行分开,两张表多加一个属性,让着两个属性产生关联。有的人会说这两个多家的属性不也冗余,但是节省空间了,并且降低了耦合度。

我们来看看案例:
我们需要设计两个表,班级表是主表,学生表是从表。

create table myclass (
id int primary key,
name varchar(30) not null comment'班级名'
);
create table stu (
id int primary key,
name varchar(30) not null comment '学生名',
class_id int,
foreign key (class_id) references myclass(id)
);

在这里插入图片描述
再主表和从表中插入数据:
在这里插入图片描述
通过结果来看,我们发现主表中没有的数据,再从表中插入不进去,那么我们万一想要删除主表的数据呢??

在这里插入图片描述

我们发现从表里面还有数据和主表的数据关联,所以删除失败,但从表的数据和主表的没有关联了,就可以删除成功了。

大家可以通过班级和班级的学生来想上面的问题。

如何理解外键:

首先我们承认,这个世界是数据很多都是相关性的。
理论上,上面的例子,我们不创建外键约束,就正常建立学生表,以及班级表,该有的字段我们都有。
此时,在实际使用的时候,可能会出现什么问题?
有没有可能插入的学生信息中有具体的班级,但是该班级却没有在班级表中?
比如学校只开了100班,101班,但是在上课的学生里面竟然有102班的学生(这个班目前并不存在),这很明显是有问题的。
因为此时两张表在业务上是有相关性的,但是在业务上没有建立约束关系,那么就可能出现问题。
解决方案就是通过外键完成的。建立外键的本质其实就是把相关性交给mysql去审核了,提前告诉mysql
表之间的约束关系,那么当用户插入不符合业务逻辑的数据的时候,mysql不允许你插入

九、案例

有一个商店的数据,记录客户及购物情况,有以下三个表组成:
商品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)
要求:
每个表的主外键
客户的姓名不能为空值
邮箱不能重复
客户的性别(男,女)

-- 创建数据库
create database if not exists bit32mall
default character set utf8 ;
-- 选择数据库
use bit32mall;
-- 创建数据库表
-- 商品
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)
);

十、总结

我们这篇讲解了关于表的约束,使我们再插入数据的时候更加合法了,大家还是要下来自己去测试一下每种约束的特点,这样印象会更加深刻,但是这一系列操作都是再定义表,还是属于数据定义语言层面,下一篇我们开始介绍数据操纵语言,前面想当于定义好结构,下一篇开始进行操作。希望大家过来支持博主

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/582841.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis管道

问题引出 Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务。一个请求会遵循以下步骤: 1 客户端向服务端发送命令分四步(发送命令→命令排队→命令执行→返回结果),并监听Socket返回,通常以阻塞模式等待服务端响应。 2 服务端…

B (1038) : DS哈希查找—二次探测再散列

文章目录 一、题目描述二、输入与输出1.输入2.输出 三、参考代码 一、题目描述 定义哈希函数为H(key) key%11。输入表长(大于、等于11),输入关键字集合,用二次探测再散列构建哈希表,并查找给定关键字。 二、输入与输…

用户规模破亿!基于文心一言的创新应用已超4000个

🤵‍♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞&#x1f4…

1.3MySQL中的自连接

自己的表和自己连接,核心:一张表拆为两张一样的表。 语法:select 字段列表 from 表 [as] 表别名1,表 [as] 表别名2 where 条件...; 关于怎样把一个表拆分成一个表,只要给它们分别取别名就行 categoryidpidcategoryname21信息…

Analytify Pro Google Analytics Goals Addon谷歌分析目标插件

Analytify Pro Google Analytics Goals Addon谷歌分析目标插件是一款极其巧妙且具有开创性的工具,它赋予用户细致跟踪和全面分析其网站性能的卓越能力。有了这个非凡的插件,个人可以毫不费力地建立并认真监控他们的Google Analytics目标,从而…

conda环境下Could not build wheels for dlib解决方法

1 问题描述 在安装模型运行的conda环境时,出现如下问题: Building wheels for collected packages: basicsr, face-alignment, dlib, ffmpy, filterpy, futureBuilding wheel for basicsr (setup.py) ... doneCreated wheel for basicsr: filenamebasi…

记录一下亿级别数据入库clickhouse

需求背景 公司的业务主要是广告数据归因的,每天的pv数据和加粉数据粗粗算一下,一天几千万上亿是有的。由于数据量大,客户在后台查询时间跨度比较大的数据时,查询效率就堪忧。因而将数据聚合后导到clickhouse进行存储,…

32阵元 MVDR和DREC DOA估计波束方向图对比

32阵元 MVDR和DREC DOA估计波束方向图对比 一、原理 MVDR原理:https://zhuanlan.zhihu.com/p/457528114 DREC原理(无失真响应特征干扰相消器):http://radarst.ijournal.cn/html/2019/3/201903018.html 主要参数: 阵…

完全适配各类中小医院专科医院和诊所的云HIS系统源码【前端:Angular+Nginx ,后台:SpringBoot】

云HIS系统采用SaaS软件应用服务模式,提供软件应用服务多租户机制,实现一中心部署多机构使用。相对传统HIS单机构应用模式,它可灵活应对区域医疗、医疗集团、医联体、连锁诊所、单体医院等应用场景,并提升区域内应用的标准化与规范…

Java技术栈 —— Nginx的使用

Java技术栈 —— Nginx的使用 一、认识Nginx二、搭建Nginx环境2.1 在Ubuntu上安装Nginx 三、使用Nginx3.1 配置负载均衡(HTTP) 一、认识Nginx 企业需要运行多个相同的副本,并将负载分散在整个系统集群上,为了高性能的负载均衡,引入了Nginx代…

通过C++程序实现光驱的自动化刻录和读取

文章目录 ISO文件格式光盘的基本概念光盘种类特点DVDR光盘使用windows调用Linux调用Linux平台下用到的C库:读取设备驱动列表向光驱中写文件 数字存储媒体快速发展的今天,光驱的使用已经不像以前那样普及了。但是在数据备份、安装软件和操作系统、旧设备兼容等领域还…

PiflowX大数据流水线系统

PiflowX大数据流水线系统。支持分布式计算引擎flink和spark。以所见即所得的方式,实现大数据采集、处理、存储与分析流程化配置、运行与智能监控。 PiflowX基于Piflow(PiFlow: 混合型科学大数据流水线系统,包含丰富的处理器组件,…

算法导论复习(七) 动态规划

动态规划一般用来求解最优化问题 设计一个动态规划算法一般有以下四步: 描述一个最优解的结构特征。递归地定义最优解的值。计算最优解的值,通常采用自底向上的方法。利用计算出的信息构造出一个最优解。 钢条切割问题 体现了动态规划的一个重要性质&a…

k8s 网络

还没有部署网络。 k8s的网络类型: k8s中的通信模式: 1,pod内部之间容器和容器之间的通信。 在同一个pod中的容器共享资源和网络,使用同一个网络命名空间。可以直接通信的。 2,同一个node节点之内不同pod之间的通信。…

大创项目推荐 深度学习YOLO抽烟行为检测 - python opencv

文章目录 1 前言1 课题背景2 实现效果3 Yolov5算法3.1 简介3.2 相关技术 4 数据集处理及实验5 部分核心代码6 最后 1 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 基于深度学习YOLO抽烟行为检测 该项目较为新颖,适合作为竞赛课…

BAQ压缩MATLAB仿真

本专栏目录: ​​​​​​​全球SAR卫星大盘点与回波数据处理专栏目录-CSDN博客 我们按照上一期文章的BAQ原理编写MATLAB代码,进行baq压缩与解压缩的全流程验证,并分析BAQ压缩对信号指标造成的影响。 生成3个点目标回波数据,加入高斯噪声,对回波进行BAQ压缩和解BAQ压缩,…

具有出色的数据速率、SI8642BA-AUR、SI8642BB-AS1R、SI8641BB-B-IUR、SI8635BD-B-ISR低功耗数字隔离器

一、简介 Si86xx 超低功耗数字隔离器系列是CMOS器件,与传统隔离技术相比,具有出色的数据速率、传播延迟、功耗、尺寸、可靠性和外部BOM优势。这些产品的工作参数在宽温度范围内和整个设备使用寿命内保持稳定,便于设计和高度统一的性能。所有…

java毕业设计—基于SpringBoot的小米商城的设计与实现

1,绪论 1.1 背景调研 电子商城的建设,不仅仅是初级网上购物的实现,它能够有效地在Internet上构架安全的和易于扩展的业务框架体系,实现BToB(企业对企业)、BToC(企业对用户)以及CTo…

首次使用TypeScript,报错:无法重新声明块级范围变量(声明变量报错)

前几天在书写TypeScript代码时,出现了声明变量报错的情况,具体情况如下: let arr: number; arr 10; console.log(arr);报错如下: 解决方案: 在配置文件tsconfig.json中,配置如下代码: { &q…

【计算机毕业设计】SSM医疗药品采购系统

项目介绍 ssm医疗药品采购系统。主要功能有: 用户管理:管理员列表; 采购管理:采购列表; 药品出库:药品出库; 库存管理:库存统计; 数据维护:药品列表、仓库…