MySQL的多种约束

事实上,写入表的数据只有数据类型上的约束,但是没有其他更为严格为约束(例如 48.2kg 中的 48.2 填在体重字段里是符合浮点类型的约束的,但是万一该数据填入到另外一个身高字段里呢?),就有可能导致用户产生错误输入。通过约束,就可以倒逼程序员做正确的输入,保证数据库中的数据是符合预期的、合法的(数据库处的数据检查几乎是检验数据合法的最后一条防线)。

1.空属性

NULL 表示“没有”(默认)和 NOT NULL 代表“不为空”,而 ''"" 表示空字符串。在实际开发中,应该尽可能保证字段不为空,因为数据为空的不能参与运算。只要字段的属性设置为 not null 时,就会硬性要求用户的数据项在对应字段处的输入不为空且不能忽略(除非后续设置了默认值,这个后面提及),否则不允许插入该数据项。

那怎么添加呢?在创建表时,在对应不为空的字段使用 NOT NULL 即可,即:CREATE TABLE IF NOT EXISTS table_name(field_name TYPE NOT NULL);,这样就形成了一种“非空约束”。

2.默认值

某一个字段的数据在大部分情况下都是一个值,只有在少数情况下才会发生变动,因此就需要为字段设置一个默认值,一般字段的默认值为 NULL,可以使用 DESC table_name; 查询 Default 所设定的默认值。其设置方法和非空属性设置类似,即:CREATE TABLE IF NOT EXISTS table_name(field_name TYPE DEFAULT default_value);,并且 NO NULLDEFAULT 可以叠加使用,其意义是:不允许数据为 NULL 值。但是,有一种情况是不允许叠加使用的,也就是 NOT NULL DEFAULT NULL

注意:一般使用 DEFAULT 就不会使用 NOT NULL,因为设置了 DEFAULT 一般就不会为空。

3.列描述

列描述是类似注释一样的存在,没有其他实际含义,主要是给程序员和 DBA 数据库管理员做提示使用,使用方法和之前的语法差不多,也是加在字段后面即可,即:CREATE TABLE IF NOT EXISTS table_name(field_name TYPE COMMENT 'comment_text');,这只是一种软性约束,其说明实质就是一种注释(不过需要注意的是,使用 DESC 是看不到注释信息的,但是使用 SHOW CREATE 是可以的)。

4.zerofill

我们之前创建表格的时候,其实故意忽略了一个问题,请看下面操作:

# 创建表时的细节
mysql> create table if not exists my_table(number int unsigned not null);
Query OK, 0 rows affected (0.02 sec)mysql> desc my_table;
+--------+------------------+------+-----+---------+-------+
| Field  | Type             | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+-------+
| number | int(10) unsigned | NO   |     | NULL    |       |
+--------+------------------+------+-----+---------+-------+
1 row in set (0.00 sec)mysql> show create table my_table\G
*************************** 1. row ***************************Table: my_table
Create Table: CREATE TABLE `my_table` (`number` int(10) unsigned NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

不是说 int4 字节的数据么?这个 int(10)10 又是什么意思?实际上如果 ZEROFILL 没有被设置,这个 10 是没有太大意义的。如果设置了 ZEROFILL,会根据这个数字来填充 0,直到 0 和数据位数达到该数字(也就是类似 C 语言使用 printf() 的数据补零修改宽度的操作),补零的目的只是为了显示上更加美观简洁一些,使表数据在显示上是等宽的。而我们也可以在 int() 里填上数字来规定等宽的长度,如果用户没有设定宽度,则会填上默认的宽度(不同类型的宽度可能不同)。

# 修改数据宽度
mysql> insert into my_table (number) values (5);
Query OK, 1 row affected (0.00 sec)mysql> insert into my_table (number) values (500);
Query OK, 1 row affected (0.00 sec)mysql> select * from my_table;
+------------+
| number     |
+------------+
| 0000000005 |
| 0000000500 |
+------------+
2 rows in set (0.00 sec)mysql> alter table my_table modify number int(2) unsigned zerofill;
Query OK, 0 rows affected (0.08 sec)
Records: 0  Duplicates: 0  Warnings: 0mysql> select * from my_table;
+--------+
| number |
+--------+
|     05 |
|    500 |
+--------+
2 rows in set (0.00 sec)

注意:补零操作并不影响查找,也是一种软规定。

5.主键

PRIMARY KEY 用来约束字段里的数据为唯一的、不可重复、不为空的,一张表最多只有一个主键,主键所在的列通常是整数类型。使用方法和上述约束类似。主键约束使得某一项数据的某一类型的数据只能有一份。根据主键来搜索,绝对只能检索到一条记录。

而使用 ALTER TABLE table_name DROP PRIMARY KEY; 即可去除表内设置的主键。

而修改某一些为主键时,就需要保证该列没有重复的数据,再使用 ALTER TABLE table_name ADD PRIMARY KEY(field_name);

还可以设置复合主键(多个列/字段组合为一个主键),只需要在定义好字段名称和字段类型后,使用 PRIMARY KEY(field_name_1, field_name_2, ...) 即可,然后使用 DESC 查看表的属性就会发现,设置为主键的相关字段在 key 出都会显示 PRI 的提示字样。

# 使用复合主键
mysql> create table my_table(-> id int unsigned,-> course_id int unsigned comment '课程编号',-> score tinyint unsigned comment '课程得分',-> primary key(id, course_id)-> );mysql> desc my_table;
+-----------+---------------------+------+-----+---------+-------+
| Field     | Type                | Null | Key | Default | Extra |
+-----------+---------------------+------+-----+---------+-------+
| id        | int(10) unsigned    | NO   | PRI | NULL    |       |
| course_id | int(10) unsigned    | NO   | PRI | NULL    |       |
| score     | tinyint(3) unsigned | YES  |     | NULL    |       |
+-----------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)mysql> insert into my_table values(001, 41, 90);
Query OK, 1 row affected (0.00 sec)mysql> desc my_table;
+-----------+---------------------+------+-----+---------+-------+
| Field     | Type                | Null | Key | Default | Extra |
+-----------+---------------------+------+-----+---------+-------+
| id        | int(10) unsigned    | NO   | PRI | NULL    |       |
| course_id | int(10) unsigned    | NO   | PRI | NULL    |       |
| score     | tinyint(3) unsigned | YES  |     | NULL    |       |
+-----------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)mysql> insert into my_table values(001, 41, 90);
Query OK, 1 row affected (0.00 sec)mysql> insert into my_table values(002, 41, 89);
Query OK, 1 row affected (0.00 sec)mysql> select * from my_table;
+----+-----------+-------+
| id | course_id | score |
+----+-----------+-------+
|  1 |        41 |    90 |
|  2 |        41 |    89 |
+----+-----------+-------+
2 rows in set (0.00 sec)mysql> insert into my_table values(001, 41, 78);
ERROR 1062 (23000): Duplicate entry '1-41' for key 'PRIMARY'

可以看到,复合主键中的各个字段是允许重复的,但是整体不能重复,要统一看作一个主键。

6.自增长

AUTO_INCREMENT 实际上是主键的一种(一般会先设置为主键约束),一张表最多只有一个自增长约束,且对应字段必须是整型,使用方法和前面类似。

设定完后,插入一个记录就会自动加 1(从 1 开始自增,当然也可以自己插入初始值)。

另外,还可以使用 SELECT LAST_INSERT_ID() 来查询最后一个增长的最大数字。

同样,一个表一般只有一个自增长约束。

7.唯一键

和主键类似,唯一键约束 unique 可以保证一个字段的数据保持唯一性(不会出现重复的数据),但是和主键不同的是,一张表只能有一个主键,但可以有多个唯一键。

成功设置为唯一键时,使用 DESC table_name 则会在 key 处显示 UNI

另外,唯一键的字段可以插入空值(但是主键不可以插入为 NULL),并且不作唯一性比较。

补充:主键和唯一键在很多地方时重叠的,但是一般主键是标识一个记录的唯一性,一般和业务无关(这样业务改变也无需变动主键),但是唯一键更多是为了保证在业务上不出现数据重复的问题。两者是互相补充的,不是互相独立、对立的。

8.外键

外键的语法为 [CONSTRAINT foreign_key_name] FOREIGN KEY (field_name) REFERENCES main_table(main_field_name); 有些时候,表与表之间是会产生关系/依赖的。因此外键和之前所有的键不太一样,是根据其他数据表来产生约束的。

# 研究使用外键的场景
mysql> create table student( s_id int unsigned primary key auto_increment,
s_name varchar(20) not null, s_telphone varchar(32) not null, c_id int );
Query OK, 0 rows affected (0.04 sec)mysql> create table class( c_id int unsigned primary key auto_increment, c_
name varchar(20) not null );
Query OK, 0 rows affected (0.04 sec)mysql> desc student;
+------------+------------------+------+-----+---------+----------------+
| Field      | Type             | Null | Key | Default | Extra          |
+------------+------------------+------+-----+---------+----------------+
| s_id       | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| s_name     | varchar(20)      | NO   |     | NULL    |                |
| s_telphone | varchar(32)      | NO   |     | NULL    |                |
| c_id       | int(11)          | YES  |     | NULL    |                |
+------------+------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)mysql> desc class;
+--------+------------------+------+-----+---------+----------------+
| Field  | Type             | Null | Key | Default | Extra          |
+--------+------------------+------+-----+---------+----------------+
| c_id   | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| c_name | varchar(20)      | NO   |     | NULL    |                |
+--------+------------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)mysql> insert into class (c_id, c_name) values (1, '101');
Query OK, 1 row affected (0.00 sec)mysql> insert into class (c_name) values ('102');
Query OK, 1 row affected (0.00 sec)mysql> insert into class (c_name) values ('103');
Query OK, 1 row affected (0.01 sec)mysql> select * from class;
+------+--------+
| c_id | c_name |
+------+--------+
|    1 | 101    |
|    2 | 102    |
|    3 | 103    |
+------+--------+
3 rows in set (0.01 sec)mysql> insert into student (s_id, s_name, s_telphone, c_id) values (1, 'lim
ou', '13455657787', 3);
Query OK, 1 row affected (0.00 sec)mysql> insert into student (s_name, s_telphone, c_id) values ('dimou', '135
55652387', 3);
Query OK, 1 row affected (0.00 sec)mysql> insert into student (s_name, s_telphone, c_id) values ('eimou', '13255232000', 2);
Query OK, 1 row affected (0.00 sec)mysql> insert into student (s_name, s_telphone, c_id) values ('wimou', '135
44232001', 1);
Query OK, 1 row affected (0.01 sec)mysql> select * from student;
+------+--------+-------------+------+
| s_id | s_name | s_telphone  | c_id |
+------+--------+-------------+------+
|    1 | limou  | 13455657787 |    3 |
|    2 | dimou  | 13555652387 |    3 |
|    3 | eimou  | 13255232000 |    2 |
|    4 | wimou  | 13544232001 |    1 |
+------+--------+-------------+------+
4 rows in set (0.00 sec)

上述的学生信息录入的过程确实没毛病,但是程序员很有可能给一个学生插入一个不存在的 c_id(甚至是将原班级删除导致 c_id 不存在),为了防止这种情况下的产生,就诞生了外键。

# 使用外键
# 先删除原先的数据表
mysql> drop table student;# 重新建立带有外键的数据表
mysql> create table student(s_id int unsigned primary key, s_name varchar(20) not null, s_telphone varchar(32) unique, c_id int unsigned, foreign key
(c_id) references class(c_id) );
Query OK, 0 rows affected (0.06 sec)mysql> desc student;
+------------+------------------+------+-----+---------+-------+
| Field      | Type             | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------+-------+
| s_id       | int(10) unsigned | NO   | PRI | NULL    |       |
| s_name     | varchar(20)      | NO   |     | NULL    |       |
| s_telphone | varchar(32)      | YES  | UNI | NULL    |       |
| c_id       | int(10) unsigned | YES  | MUL | NULL    |       |
+------------+------------------+------+-----+---------+-------+
4 rows in set (0.00 sec)mysql> select * from class;
+------+--------+
| c_id | c_name |
+------+--------+
|    1 | 101    |
|    2 | 102    |
|    3 | 103    |
+------+--------+
3 rows in set (0.00 sec)# 尝试插入数据
mysql> insert into student values (1, 'limou', '13455657787', 3);
Query OK, 1 row affected (0.01 sec)mysql> insert into student values (2, 'dimou', '13555652387', 3);
Query OK, 1 row affected (0.00 sec)mysql> insert into student values (3, 'eimou', '13255232000', 2);
Query OK, 1 row affected (0.00 sec)mysql> insert into student values (4, 'wimou', '13544232001', 1);
Query OK, 1 row affected (0.01 sec)mysql> insert into student values (5, 'fimou', '13514875183', 4);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`limou_database`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`c_id`) REFERENCES `class` (`c_id`))# 尝试直接删除被子表引用为外键的父行
mysql> select * from student;
+------+--------+-------------+------+
| s_id | s_name | s_telphone  | c_id |
+------+--------+-------------+------+
|    1 | limou  | 13455657787 |    3 |
|    2 | dimou  | 13555652387 |    3 |
|    3 | eimou  | 13255232000 |    2 |
|    4 | wimou  | 13544232001 |    1 |
|    6 | fimou  | 13514875183 |    2 |
|    7 | fimou  | 13514875123 |    3 |
+------+--------+-------------+------+
6 rows in set (0.00 sec)mysql> select * from class;
+------+--------+
| c_id | c_name |
+------+--------+
|    1 | 101    |
|    2 | 102    |
|    3 | 103    |
+------+--------+
3 rows in set (0.00 sec)mysql> delete from class where c_id=3;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`limou_database`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`c_id`) REFERENCES `class` (`c_id`)) # 很明显删除失败# 去除子表对父表的引用,再尝试删除
mysql> delete from student where c_id=3;
Query OK, 3 rows affected (0.01 sec)mysql> delete from class where c_id=3;
Query OK, 1 row affected (0.00 sec) # 很明显删除成功

可以看到,最后一次插入出现了错误,说明外键约束生效。

另外 [CONSTRAINT foreign_key_name] 实际上是给外键起一个别名,是可选做法,不设定则会有默认的名字。

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

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

相关文章

Maven的下载安装配置教程

一、简单了解一下什么是Maven Maven就是一款帮助程序员构建项目的工具,我们只需要告诉Maven需要哪些Jar 包,它会帮助我们下载所有的Jar,极大提升开发效率。 1.Maven翻译为“专家“, ”内行”的意思,是著名Apache公司下…

Unity基于AssetBundle资源管理流程详解

在Unity游戏开发中,资源管理是一个非常重要的环节。随着游戏的发展,资源会变得越来越庞大,因此需要一种高效的资源管理方式来减少内存占用和加快加载速度。AssetBundle是Unity提供的一种资源打包和加载方式,可以将资源打包成一个独…

Fiddler工具 — 19.Fiddler抓包HTTPS请求(二)

5、查看证书是否安装成功 方式一: 点击Tools菜单 —> Options... —> HTTPS —> Actions 选择第三项:Open Windows Certificate Manager打开Windows证书管理器。 打开Windows证书管理器,选择操作—>查看证书,在搜索…

【Java程序员面试专栏 数据结构】四 高频面试算法题:哈希表

一轮的算法训练完成后,对相关的题目有了一个初步理解了,接下来进行专题训练,以下这些题目就是汇总的高频题目,一个O(1)查找的利器哈希表,所以放到一篇Blog中集中练习 题目关键字解题思路时间空间两数之和辅助哈希使用map存储出现过的值,key为值大小,value为下标位置,…

船舶维保管理系统|基于springboot船舶维保管理系统设计与实现(源码+数据库+文档)

船舶维保管理系统目录 目录 基于springboot船舶维保管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、船舶列表 2、公告信息管理 3、公告类型管理 4、维保计划管理 5、维保计划类型管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、…

网络安全-pikachu之SQL注入漏洞(数字型注入)

哦,SQL注入漏洞,可怕的漏洞。 在owasp发布的top10排行榜里,注入漏洞一直是危害排名第一的漏洞,其中注入漏洞里面首当其冲的就是数据库注入漏洞。 一个严重的SQL注入漏洞,可能会直接导致一家公司破产! SQL注入漏…

剑指offer面试题17 合并俩个排序的列表

考察点 链表知识点 链表的遍历题目 分析 题目要求合并俩个排序的列表,很自然的可以想到从俩个链表的头结点开始比较,假设a链表的头结点比b链表的头结点小,那么a链表的头结点就是合并后链表的头结点,接下来也是很自然的可以想到…

Day3 javaweb开发——登录认证

登录功能 没什么好写的,就是LoginController层里面要注入empService的对象 登录校验(重点) 没有校验的情况 没有登录之前,访问数据的网址需要跳转到登录页面。 http是无状态的,处理其他业务时没有判断他是否登录 …

Apache POI技术-在Java中的基本使用

Apache POI技术-在Java中的基本使用 文章目录 Apache POI技术-在Java中的基本使用前言一、Apache POI是什么?1.Apache POI简介:2.Apache POI主要包括的模块:3.Apache POI 的应用场景:报表生成:数据导入导出&#xff1a…

HarmonyOS—LocalStorage:页面级UI状态存储

LocalStorage是页面级的UI状态存储,通过Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。LocalStorage也可以在UIAbility实例内,在页面间共享状态。 本文仅介绍LocalStorage使用场景和相关的装饰器:LocalStorageProp和LocalS…

高级统计方法 第1次作业

概念 1. 请解释什么是P值,怎么计算p值,p值结果怎么理解,p值有哪些应用......? (a)什么是P值 P值是一种用来判定假设检验结果的一个参数,它描述了在原假设为真的情况下,比所得到的…

【JavaScript】字符串的正则匹配和替换

文章目录 1. 字符串的正则匹配1.1 test() 方法1.2 match() 方法 2. 字符串的正则替换2.1 替换所有匹配项2.2 使用匹配组2.3 使用函数进行替换 3. 常见应用场景3.1 删除非数字字符3.2 格式化货币 4. 总结 在 JavaScript 中,字符串的正则匹配和替换是常见的操作&#…

【K-means聚类】

K-means聚类python代码实现 聚类k-means聚类代码 聚类 定义:聚类是一种无监督的机器学习方法,它的主要目的是将数据集中的对象(或点)按照它们之间的相似性分组或聚类。这些聚类(或称为簇)中的对象在某种度…

Docker技术仓库

数据卷 为什么用数据卷? 宿主机无法直接访问容器中的文件容器中的文件没有持久化,导致容器删除后,文件数据也随之消失容器之间也无法直接访问互相的文件 为解决这些问题,docker加入了数据卷机制,能很好解决上面问题…

FPGA模块——IIC接口设计

FPGA模块——IIC接口设计 IIC协议IIC接口代码应用IIC接口的代码 IIC协议 IIC接口代码 module iic_drive#(parameter P_ADDR_WIDTH 16 )( input i_clk ,//模块输入时钟input i_rs…

嵌入式培训机构四个月实训课程笔记(完整版)-Linux ARM驱动编程第八天-高级驱动framebuffer(物联技术666)

链接:https://pan.baidu.com/s/1cd7LOSAvmPgVRPAyuMX7Fg?pwd1688 提取码:1688 帧缓冲(framebuffer)设备应用于linux显示技术方面。因为linux的显示平台已经全部基于framebuffer,所以目前在linux环境下开发图形化界面…

python opencv图像模糊

目录 一:均值滤波 二:高斯滤波 三:中值滤波 四:双边滤波 在OpenCV中,模糊图片或进行图像平滑处理时常用的方法包括以下几种: 均值滤波 (Blurring): 均值滤波是一种简单的平滑方法,它通过对图像中每个像素的邻域内像素值进行平均来计算新的像素值。在OpenC

ABC341 题解

ABC341 题解 A Description 给定一个数 N N N,求长度 2 N 1 2N1 2N1 的 01 交替的字符串(0 开始)。 Solution 直接模拟,注意 0-index 是 i m o d 2 i\bmod 2 imod2,1-index 是 ( i 1 ) m o d 2 (i1) \bmod …

js-Vue Router 中的方法,父A-子B-子C依次返回,无法返回到A,BC中形成循环跳转解决

1.常用的方法 在 Vue Router 中,有一些常用的方法用于实现路由导航和管理。以下是一些常见的 Vue Router 方法及其作用: push: router.push(location, onComplete, onAbort) 作用:向路由历史记录中添加一个新条目,并导航到指定的路…

算法-位运算

题目&#xff1a;题目5 一个数组中有一种数出现K次&#xff0c;其他数都出现了M次&#xff0c; M > 1, K < M 找到&#xff0c;出现了K次的数&#xff0c; 要求&#xff0c;额外空间复杂度O(1)&#xff0c;时间复杂度O(N) 思路&#xff1a;遍历数组按位计数&#xff0c;不…