MySQL篇【5】——约束

news2024/12/28 4:15:11

目录

  • 表的约束
    • 空属性
    • 默认值
    • 列描述
    • zerofill
    • 主键
    • 自增长
    • 唯一键
    • 外键
      • 如何理解外键约束

在数据库的实际操作中难免会有一些操作不规范的地方,比方说在一张学生成绩表中,成绩的最高值为100,那么如果在这张表中如果出现了超过100分的成绩那显然是不合理的,因次需要添加约束来避免这些错误

表的约束

真正约束字段的是数据类型(比方说int类型只能存储整数),但是数据类型约束很单一,需要一些额外的约束,更好的保证数据的合法性,从业务逻辑角度保证数据的正确性。比如有一个字段是tel,要求是唯一的。
表的约束很多,本篇主要介绍:null/ not null, default, comment, zerofill, primary key, auto_increment, unique key

空属性

  • 两个值:null(默认的)和not null
  • 数据库默认字段基本都是字段可以为空,但是实际开发时,尽可能保证字段不为空,因为数据为空没办法参与运算
mysql> select null;
+------+
| NULL |
+------+
| NULL |
+------+
1 row in set (0.00 sec)

mysql> select 1+null;
+--------+
| 1+null |
+--------+
|   NULL |
+--------+
1 row in set (0.00 sec)

案例:
创建一个班级表,包含班级名和班级所在的教室,班级和教室名字不能为空。

mysql> create table myclass(
    -> class_name varchar(20) not null,
    -> class_room varchar(10) not null
    -> );
Query OK, 0 rows affected (0.05 sec)

mysql> desc myclass;
+------------+-------------+------+-----+---------+-------+
| Field      | Type        | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| class_name | varchar(20) | NO   |     | NULL    |       |
| class_room | varchar(10) | NO   |     | NULL    |       |
+------------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

mysql> insert into myclass(class_name,class_room) values('class1', 'a101');
Query OK, 1 row affected (0.00 sec)

mysql> insert into myclass(class_name,class_room) values('class2');
ERROR 1136 (21S01): Column count doesn't match value count at row 1

默认值

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

mysql> desc tt13;
+-------+---------------------+------+-----+---------+-------+
| Field | Type                | Null | Key | Default | Extra |
+-------+---------------------+------+-----+---------+-------+
| name  | varchar(20)         | NO   |     | NULL    |       |
| age   | tinyint(3) unsigned | YES  |     | 0       |       |
| sex   | char(2)             | YES  |     ||       |
+-------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
mysql> insert into tt13(name) values('jack');
Query OK, 1 row affected (0.01 sec)

mysql> select * from tt13;
+------+------+------+
| name | age  | sex  |
+------+------+------+
| jack |    0 ||
+------+------+------+
1 row in set (0.00 sec)

列描述

列描述:comment,没有实际含义,专门用来描述字段,会根据表创建语句保存,用来提醒程序员或DBA

mysql> create table tt14( name varchar(20) not null comment'姓名', age tinyint unsigned default 0 comment '年龄', sex char(2) default '男' comment '姓别' );
Query OK, 0 rows affected (0.07 sec)

通过desc看不到注释信息,但可以通过show看到:

mysql> show create table tt14\G
*************************** 1. row ***************************
       Table: tt14
Create Table: CREATE TABLE `tt14` (
  `name` varchar(20) NOT NULL COMMENT '姓名',
  `age` tinyint(3) unsigned DEFAULT '0' COMMENT '年龄',
  `sex` char(2) DEFAULT '男' COMMENT '姓别'
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

zerofill

在创建表时,有时会看见数字类型后面会加一个数字比方说下面的int(10),这代表什么意思?

mysql> create table tt15(
    -> a int(10) unsigned,
    -> b int(10) unsigned
    -> );
Query OK, 0 rows affected (0.06 sec)

如果没有zerofill这个属性,括号内的数字时毫无意义的

// 没有zerofill属性
mysql> insert into tt15(a,b) values(1,2);
Query OK, 1 row affected (0.04 sec)

mysql> select * from tt15;
+------+------+
| a    | b    |
+------+------+
|    1 |    2 |
+------+------+
1 row in set (0.00 sec)
//添加zerofill属性
mysql> alter table tt15 change a a int(5) unsigned zerofill;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show create table tt15\G
*************************** 1. row ***************************
       Table: tt15
Create Table: CREATE TABLE `tt15` (
  `a` int(5) unsigned zerofill DEFAULT NULL,
  `b` int(10) unsigned DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql> select * from tt15;
+-------+------+
| a     | b    |
+-------+------+
| 00001 |    2 |
+-------+------+
1 row in set (0.00 sec)

这次可以看到a的值由1变成00001,这就是zerofill属性的作用,如果宽度小于设定的宽度,自动填充0,不过这只是显示的结果,在MySQL中实际存储的还是1,可以用hex()(十六进制转换)函数来证明

mysql> select a, hex(a) from tt15;
+-------+--------+
| a     | hex(a) |
+-------+--------+
| 00001 | 1      |
+-------+--------+
1 row in set (0.00 sec)

主键

主键primary key用来约束该字段里的数据不能重复,不能为空,一张表最多只能由一个主键;主键所在的列通常是整数类型。
案例:

  • 创建表的时候直接在字段上指定主键
mysql> create table tt16( id int unsigned primary key, name char(20) not null );
Query OK, 0 rows affected (0.04 sec)

mysql> desc tt16;
+-------+------------------+------+-----+---------+-------+
| Field | Type             | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| id    | int(10) unsigned | NO   | PRI | NULL    |       |
| name  | char(20)         | NO   |     | NULL    |       |
+-------+------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
  • 主键约束:主键对应的字段中不能重复,一旦重复,操作失败
mysql> insert into tt16(id,name) values(1,'aaa');
Query OK, 1 row affected (0.01 sec)

mysql> insert into tt16(id,name) values(1,'aaa');
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
  • 当表创建好以后但是没有主键的时候,可以再次追加主键
alter table tablename add primary key(coloum);
  • 删除主键
mysql> alter table tt16 drop primary key;
Query OK, 1 row affected (0.09 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> desc tt16;
+-------+------------------+------+-----+---------+-------+
| Field | Type             | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| id    | int(10) unsigned | NO   |     | NULL    |       |
| name  | char(20)         | NO   |     | NULL    |       |
+-------+------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
  • 复合主键
    在创建表的时候,在所有字段之后,使用primary key(主键字段列表)来创建主键,如果有多个字段作为主键,可以使用复合主键
mysql> create table tt17(
    -> id int unsigned,
    -> course char(10),
    -> score tinyint unsigned default 60,
    -> primary key(id,course)
    -> );
Query OK, 0 rows affected (0.04 sec)

mysql> desc tt17;
+--------+---------------------+------+-----+---------+-------+
| Field  | Type                | Null | Key | Default | Extra |
+--------+---------------------+------+-----+---------+-------+
| id     | int(10) unsigned    | NO   | PRI | NULL    |       |
| course | char(10)            | NO   | PRI | NULL    |       |
| score  | tinyint(3) unsigned | YES  |     | 60      |       |
+--------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

#插入数据
mysql> insert into tt17(id,course,score) values(1,'123',60);
Query OK, 1 row affected (0.01 sec)

mysql> insert into tt17(id,course,score) values(1,'123',60);
ERROR 1062 (23000): Duplicate entry '1-123' for key 'PRIMARY'
mysql> insert into tt17(id,course,score) values(2,'123',60);
Query OK, 1 row affected (0.00 sec)

mysql> insert into tt17(id,course,score) values(1,'124',60);
Query OK, 1 row affected (0.01 sec)

从上面的例子可以看出复合主键插入时,只有复合主键中的每一个数据都与另一条数据完全匹配才算主键冲突。

自增长

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

  • 一个字段要做自增长,前提是本身是一个索引(key一栏有值)
  • 自增长字段必须是整数
  • 一张表最多只能有一个自增长
    案例:
mysql> create table tt18( id int unsigned primary key auto_increment, name varchar(10)not null default '' );
Query OK, 0 rows affected (0.04 sec)

mysql> insert into tt18(name) values('a');
Query OK, 1 row affected (0.01 sec)

mysql> insert into tt18(name) values('b');
Query OK, 1 row affected (0.01 sec)

mysql> select * from tt18;
+----+------+
| id | name |
+----+------+
|  1 | a    |
|  2 | b    |
+----+------+
2 rows in set (0.00 sec)

在插入后获取上次插入的AUTO_INCREMENT的值(批量插入获取的是第一个值)

mysql> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
|                2 |
+------------------+
1 row in set (0.00 sec)

索引
在关系数据库中,索引是一种单独的,物理的对数据库列表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引的作用相当于图书的目录,可以根据目录中的页码快速找到目标内容。

索引提供指向存储在表的指定列中的数据值的指针,然后根据指定的排序顺序对指针排序。数据库使用索引来找到特定值,然后顺时针找到包含该值的行。这样可以使SQL语句执行得更快,更快速访问数据库表中的特定信息。

关于索引,会在后面的文章更加详细地介绍。

唯一键

一张表中往往有很多字段需要唯一性,数据不能重复,但是一张表中只能有一个主键,不过唯一键就可以解决表中有多个字段需要唯一性约束的问题。
唯一键的本质和主键差不多,唯一键允许为空,而且可以多个为空,空字段不做唯一性比较。

唯一键和主键的区别
主键更多标识唯一性,而唯一键更多在保证业务,不要和别的信息出现重复,下面来举一个例子:
某学校要做一个学生管理系统,需要保存的数据包括学生的手机号,同时需要一个字段来作为学生的主键。那么我们可以用学生的学号来作为主键吗?学生的手机号可能是会发生变化的,那么当学生的手机号发生变化时,系统的主键也会发生变化,在业务调整时,尽量不要对主键做过多调整。在上面的例子中,不同学生的手机号其实只需要保证唯一性就行了,所以我们可以选择手机号作为唯一键。
那么我们应该选择什么值来作为主键呢?尽量选择与业务无关的数据!也就是说,我们可以在存储学生信息时,新建一列id,只用来作为数据的主键
案例:

mysql> create table stu( id char(10) unique, name varchar(10) );
Query OK, 0 rows affected (0.07 sec)

mysql> insert into stu(id,name) values('01','aaa');
Query OK, 1 row affected (0.01 sec)

mysql> insert into stu(id,name) values('01','bbb'); //不可以插入相同的值
ERROR 1062 (23000): Duplicate entry '01' for key 'id'
mysql> insert into stu(id,name) values(null,'bbb'); //可以为空
Query OK, 1 row affected (0.01 sec)

mysql> select * from stu;
+------+------+
| id   | name |
+------+------+
| 01   | aaa  |
| NULL | bbb  |
+------+------+
2 rows in set (0.00 sec)

外键

外键用于定义主表和从表之间的关系:外键约束主要定义在从表上,主表则必须是有主键约束或unique约束。当定义外键后,要求外键列数据必须在主表的主键列存在或为null。

foreign key coloum references 主表(coloum);

在这里插入图片描述

  • 创建主键表
mysql> create table class(
    -> id int primary key,
    -> name varchar(30) not null
    -> );
  • 创建从表
mysql> create table stu(
    -> id int primary key,
    -> name varchar(30) not null,
    -> class_id int,
    -> foreign key(class_id) references class(id)
    -> );
  • 正常插入数据
mysql> insert into class value(10, '向日葵班'),(20, '玫瑰班');
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0
mysql> insert into stu values(1, '野原新之助',10),(2, '阿豹', 20);
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0
  • 插入一个班级号为30 的学生,因为没有这个班级,所以插入不成功
mysql> insert into stu values(3, 'ssj', 30);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`restrain`.`stu`, CONSTRAINT `stu_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`))
  • 插入班级id为null,比如来了一个学生,目前还没有分配班级
mysql> insert into stu values(3, '风间彻', null);
Query OK, 1 row affected (0.01 sec)

如何理解外键约束

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

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

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

相关文章

单片机定时器

定时器 STM32有11个定时器,2个高级定时器、4个通用定时器,2个基本定时器,1个系统嘀嗒定时器(systick),2个看门狗定时器。 定时器计算: Tout((per)psc)/Tclk t(f/pre)per…

Spire.Office for Java 7.12.2 迎接新年/圣诞!!!

谷歌找破解版Spire.Office for Java is a combination of Enterprise-Level Office Java APIs offered by E-iceblue. It includes Spire.Doc for Java, Spire.XLS for Java, Spire.Presentation for Java, Spire.PDF for Java and Spire.Barcode for Java.内容及配图来自网络 …

cv2.findContours() 图像的轮廓

cv2.findContours(image, mode, method, contoursNone, hierarchyNone, offsetNone)参数: image:寻找轮廓的图像,注意输入的图片必须为二值图片。若输入的图片为彩色图片,必须先进行灰度化和二值化 mode:轮廓的检索模…

高分子PEG: mPEG-Phosphate MV 1K 2K 3.4K 5K 10K 20K 特点分享

【中文名称】甲氧基-聚乙二醇-磷酸盐 【英文名称】 mPEG-Phosphate 【结 构 式】 【CAS号】N/A 【分子式】N/A 【MV】1000、2000、3400、5000、10000、20000 【基团部分】Phosphate PEG,磷酸盐PEG 【纯度标准】95% 【包装规格】1g,5g,10g&…

java基于Springboot的影视管理系统-计算机毕业设计

项目介绍 影城管理系统的主要使用者分为管理员和用户,实现功能包括管理员:首页、个人中心、用户管理、电影类型管理、放映厅管理、电影信息管理、购票统计管理、系统管理、订单管理,用户前台:首页、电影信息、电影资讯、个人中心…

acwing-Django项目——前期工作+前端js css

文章目录1.租服务器配置环境 配置docker环境创建工作用户ljh并赋予sudo权限配置免密登录方式给server1装环境装docker将AC Terminal中的/var/lib/acwing/docker/images/docker_lesson_1_0.tar镜像上传到租好的服务器中将镜像加载到本地配置docker环境创建项目配置git运行一下dj…

C++中前置操作性能一定优于后置操作?

后置操作和前置操作,一个会产生临时变量,一个不会产生临时变量,其原因是:前置操作遵循的规则是change-then-use,而后置操作遵循的规则是use-then-change。正因为后置操作的use-then-change原则,使得编译器在…

Python如何pip批量安装指定包 - 最简单方法

文章目录背景解决办法1. 制作requirements.txt文件2. 将requirements.txt传到需要部署的电脑上3. 批量安装包背景 有很多台服务器需要配置, 简单说也就是公司给我配备了3台Windows, 我需要配置Python环境并安装7个包, 如果按照常规的pip install我至少得安装3x721次, 并且得一…

data shift--学习笔记

一般假设训练集和测试集是独立同分布的,才能保证在训练集上表现良好的模型同样适用于测试集。当训练集和测试集不同分布时,就发生了dataset shiftdata shift类型: 协变量偏移(covariate shift): 协变量&…

简约而不简单!分布式锁入门级实现主动续期-自省

一、背景 一个分布式锁应具备的功能特点中有避免死锁这一条: 如果某个客户端获得锁之后处理时间超过最大约定时间,或者持锁期间内发生了故障导致无法主动释放锁,其持有的锁也能够被其他机制正确释放,并保证后续其它客户端也能加锁…

Unity 3D 刚体(Rigidbody)|| Unity 3D 刚体实践案例

Unity 3D 中的 Rigidbody 可以为游戏对象赋予物理特性,使游戏对象在物理系统的控制下接受推力与扭力,从而实现现实世界中的物理学现象。 我们通常把在外力作用下,物体的形状和大小(尺寸)保持不变,而且内部…

Vue3 —— Pinia 的学习指南以及案例分享

文章目录 前言一、什么是pinia?二、为什么要使用Pinia?三、Pinia对比Vuex四、具体使用方法 1.安装2.创建一个store五、state 1.访问state2.重置状态3.修改state4.批量修改state5.替换state六、getters 1.访问getters2.getters传参3.写为普通函数可调用this4.访问其他的store中…

可见光热红外图像融合算法设计

本设计方式中对于多源图像融合算法采用以下三个步骤进行: 多源图像目标特征提取;多源图像配准;多源图像融合。 1.多源图像目标特征提取 多源图像的目标特征提取中,优先对目标图像进行预处理,对于可见光图像…

品牌势能铸就非凡经典,凯里亚德与郁锦香酒店亮相品牌沙龙会烟台站

近日,汇聚国内众多投资人的锦江酒店(中国区)品牌沙龙会烟台站顺利举行。本次沙龙活动以“齐风鲁韵 锦绘未来”为主题,锦江酒店(中国区)旗下众多优秀品牌共同亮相。凯里亚德酒店与郁锦香酒店在本次活动中向投资人展示了在如今复杂多变的酒店市场中如何以强…

Java面向对象:继承

面向对象三大特征之二:继承 目录 面向对象三大特征之二:继承 1.继承是什么: 2.继承的好处 继承概述的总结 1.什么是继承?继承有什么好处? 2.继承的格式是什么样的? 3.继承后子类的特点是什么&#x…

Docker介绍及项目部署

安装Docker 关闭SELINUX服务 SELINUX是CentOS系统捆绑的安全服务程序,因为安全策略过于严格,所以建议搭建关闭这项服务 修改/etc/selinux/config文件,设置SELINUXdisabled vim /etc/selinux/config # 设置SELINUXdisabled# 设置完成后重启…

[附源码]计算机毕业设计姜太公渔具销售系统Springboot程序

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

Crane如何做到利用率提升3倍稳定性还不受损?

作为云平台用户,我们都希望购买的服务器物尽其用,能够达到最大利用率。然而要达到理论上的节点负载目标是很的,计算节点总是存在一些装箱碎片和低负载导致的闲置资源。下图展示了某个生产系统的CPU资源现状,从图中可以看出&#x…

编译器设计(十二)——指令选择

文章目录一、简介二、代码生成三、扩展简单的树遍历方案四、通过树模式匹配进行指令选择4.1 重写规则4.2 找到平铺方案五、通过窥孔优化进行指令选择5.1 窥孔优化5.2 窥孔变换程序六、高级主题6.1 学习窥孔模式6.2 生成指令序列七、小结和展望一、简介 指令选择(in…

java面试题-并发

1. 并行和并发有什么区别? 并行:多个处理器或多核处理器同时处理多个任务。并发:多个任务在同一个 CPU 核上,按细分的时间片轮流(交替)执行,从逻辑上来看那些任务是同时执行。 如下图: 并发 两个队列和一…