MySQL数据库,数据的约束

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 本文讲解:MySQL数据库,数据的约束

 image.gif编辑

目录

1.数据的约束

1.1约束的类型

1.2NULL约束

1.3UNIQUE约束

1.4DEFAULT约束

1.5PRIMARY KEY约束

1.6FOREIGN KEY约束

image.gif编辑

1.数据的约束

首先,创建一个名为test的数据库:

mysql> create database test charset utf8;
Query OK, 1 row affected (0.00 sec)
mysql> use test;
Database changed

image.gif

下方的所有测试表,都是在这个test数据库中进行创建的。


1.1约束的类型

    • NOT NULL - 指定某列不得为NULL(空)
    • UNIQUE - 唯一值,每一列的值都是不同的
    • DEFAULT - 默认值,当这列没有内容时会给定一个默认值
    • PRIMARY KEY - 主键,是NOT NULL和UNIQUE的结合意为不为空的且唯一的,方便我们快速的查找某一信息
    • FOREIGN KEY - 外键,保证一个表中的数据匹配另一个表中的值的参照完整性

    1.2NULL约束

    null也就是为空的情况,当我们创建一个表后,表中的数据的结构默认都是为null也就是可以什么都不填。当我们把这个表中的某个字段进行not null约束时,这时这个字段就不得为空了。

    创建一个测试表mytest1:

    mysql> create table mytest1(
        -> id int not null,
        -> name varchar(10));
    Query OK, 0 rows affected (0.02 sec)

    image.gif

    此时mytest1表的结构为:

    image.gif编辑


    当我进行插入数据时程序是可以正常的进行通过的:

    mysql> insert into mytest1 values(1,'张三');
    Query OK, 1 row affected (0.00 sec)

    image.gif

    此时mytest1表内容为:

    image.gif编辑

    当我们进行指定列插入,只指定name这一列进行插入时:

    mysql> insert into mytest1(name) values('李四');
    ERROR 1364 (HY000): Field 'id' doesn't have a default value

    image.gif

    出现错误ERROR 1364 (HY000): Field 'id' doesn't have a default value,错误意为:错误1364 (HY000):字段“id”没有默认值 。因此,当我在创建表的时候把id约束为了not null 那么这个字段就为必填项。通过上述讲解,详细大家已经知道了not null约束的作用了。


    1.3UNIQUE约束

    unique这个约束意为唯一值,当表中的某个字段被unique约束时。这个字段的任何一行的数据都是独立的,也就是这个表中的每一行数据之间都不得相同。

    创建一个测试表mytest2:

    mysql> create table mytest2(
        -> id int unique,
        -> name varchar(20));
    Query OK, 0 rows affected (0.02 sec)

    image.gif

    此时mytest2表的结构为:

    image.gif编辑

    多行插入,插入两行数据:

    mysql> insert into mytest2(id,name) values
        -> (1,'张三'),
        -> (2,'李四');
    Query OK, 2 rows affected (0.00 sec)
    Records: 2  Duplicates: 0  Warnings: 0

    image.gif

    此时,mytest2表的内容为:

    image.gif编辑

    当我们插入这样一条记录时:

    mysql> insert into mytest2(id,name) values(1,'王五');
    ERROR 1062 (23000): Duplicate entry '1' for key 'id'

    image.gif

    出现错误ERROR 1062 (23000): Duplicate entry '1' for key 'id',错误意为:错误1062(23000):密钥“id”的重复条目“1” 。因此,当我们的字段加上unique约束时只得插入唯一的数据。


    1.4DEFAULT约束

    default约束意为默认值,当表中某个字段被default约束时,如果该字段在插入时没有填入相应的数据时,此时该列内显示的就是被default约束的默认值。

    创建一个测试表mytest3:

    mysql> create table mytest3(
        -> id int,
        -> name varchar(20) default '阿三');
    Query OK, 0 rows affected (0.02 sec)

    image.gif

    此时mytest3的表结构为:image.gif编辑

    插入指定列id:

    mysql> insert into mytest3(id) values(1);
    Query OK, 1 row affected (0.01 sec)
    mysql> select * from mytest3;
    +------+------+
    | id   | name |
    +------+------+
    |    1 | 阿三 |
    +------+------+
    1 row in set (0.00 sec)

    image.gif

    通过上述代码我们可以发现name默认显示了阿三这条信息,这就是default的用处,设置某字段的默认值。


    1.5PRIMARY KEY约束

    primary key约束意为主键,这个约束是not null和unique的结合体,也就是当表中某个字段被primary key约束时,这个字段不得为空且不能重复。

    创建一个测试表mytest4:

    mysql> create table mytest4(
        -> id int primary key,
        -> name varchar(20));
    Query OK, 0 rows affected (0.02 sec)

    image.gif

    image.gif编辑 插入三行数据:

    mysql> insert into mytest4(id,name) values
        -> (1,'张三'),
        -> (2,'李四'),
        -> (1,'王五');
    ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'

    image.gif

    在上述代码中,第一条数据和第三条数据的id都相同了。从而提示ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY',意为:错误1062(23000):密钥“主”的重复条目“1” 。因此,当我们把一个字段设置为主键primary key时,不得插入相同的数据。


    此外,当我们想要主键以自增的形式存在时,我们可以在primary key 后面上述auto_increment这个语句。创建一个测试表,mytest5:

    mysql> create table mytest5(
        -> id int primary key auto_increment,
        -> name varchar(20));
    Query OK, 0 rows affected (0.03 sec)

    image.gif

    此时mytest5的表结构为:

    image.gif编辑 指定列插入数据,插入两行name:

    mysql> insert into mytest5(name) values('张三');
    Query OK, 1 row affected (0.01 sec)
    mysql> insert into mytest5(name) values('李四');
    Query OK, 1 row affected (0.00 sec)
    mysql> select * from mytest5;
    +----+------+
    | id | name |
    +----+------+
    |  1 | 张三 |
    |  2 | 李四 |
    +----+------+
    2 rows in set (0.00 sec)

    image.gif

    通过上述代码展示,我们可以看到我们没有插入id值时,默认插入了两行主键值,并且是以1开始往后自增的。这就是 auto_increment的用处。当然,还有一个特殊的情况,如果插入了一条较大的主键时,则自增会以较大的主键进行自增。如以下代码:

    mysql> insert into mytest5 values(100,'王五');
    Query OK, 1 row affected (0.00 sec)
    mysql> insert into mytest5(name) values('赵六');
    Query OK, 1 row affected (0.00 sec)
    mysql> select * from mytest5;
    +-----+------+
    | id  | name |
    +-----+------+
    |   1 | 张三 |
    |   2 | 李四 |
    | 100 | 王五 |
    | 101 | 赵六 |
    +-----+------+
    4 rows in set (0.00 sec)

    image.gif

    我们可以看到,在插入了一条id为100的值后,我再进行指定列name插入数据,此时的id会默认从100往后自增。因此通过上述展示,我们可以很好了解到表中的某字段主键设置为auto_increment后如果按照默认值自增的话,是按照最大值来往后自增的。


    1.6FOREIGN KEY约束

    foreign key约束是关联两个或多个表之间结构的约束,我们可以根据需求设计相应的表结构。语法格式为:foreign key (字段名) references 主表(列)

    因此发出关联的表我们称为子表,被关联的表我们称为父表。关联哪些字段也是根据你的需求来设定的,举两个例子:

    创建一个班级表classes:

    mysql> create table classes(
        -> id int primary key auto_increment
        -> );
    Query OK, 0 rows affected (0.05 sec)

    image.gif

    classes表的结构为:

    mysql> desc classes;
    +-------+---------+------+-----+---------+----------------+
    | Field | Type    | Null | Key | Default | Extra          |
    +-------+---------+------+-----+---------+----------------+
    | id    | int(11) | NO   | PRI | NULL    | auto_increment |
    +-------+---------+------+-----+---------+----------------+
    1 row in set (0.00 sec)

    image.gif

    创建一个学生表student:

    mysql> create table student(
        -> id int primary key auto_increment,
        -> name varchar(20) default '未填写',
        -> age int,
        -> sex varchar(10),
        -> classes_id int,
        -> foreign key (classes_id) references classes(id)
        -> );
    Query OK, 0 rows affected (0.02 sec)

    image.gif

    student表的结构为:

    mysql> desc student;
    +------------+-------------+------+-----+---------+----------------+
    | Field      | Type        | Null | Key | Default | Extra          |
    +------------+-------------+------+-----+---------+----------------+
    | id         | int(11)     | NO   | PRI | NULL    | auto_increment |
    | name       | varchar(20) | YES  |     | 未填写  |                |
    | age        | int(11)     | YES  |     | NULL    |                |
    | sex        | varchar(10) | YES  |     | NULL    |                |
    | classes_id | int(11)     | YES  | MUL | NULL    |                |
    +------------+-------------+------+-----+---------+----------------+
    5 rows in set (0.00 sec)

    image.gif

    经过上述两个表的创建,此时两表之间的关系为:student为子表,classes为父表。这样的关系有什么作用呢?当我们想要对子表student进行增添数据或操作时,必须满足父表classes中的id存在。且student表在增添数据时,student中的classes_id必须与classes中的id完全相同。可能有些难理解,我们来看下方的例子与讲解。


    当我往student这个空表里面增添一行数据时:

    mysql> insert into student values(1,'张三',20,'男',101);
    ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`classes_id`) REFERENCES `classes` (`id`))

    image.gif

    出现了ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`classes_id`) REFERENCES `classes` (`id`))这条错误,这条错误的意思为: 错误1452(23000):不能添加或更新子行:外键约束失败(' test ')。 ' student ',约束' student_ibfk_1 '外键(' classes_id ')引用' classes ' (' id '))

    因为student表中的classes_id连接了外键为classes表中的id,因此我们得保证classes表中的id存在的同时,才能增添数据到student表中。因此,我们应该这样写代码:

    mysql> insert into classes(id) values
        -> (101),
        -> (102),
        -> (103);
    Query OK, 3 rows affected (0.00 sec)
    Records: 3  Duplicates: 0  Warnings: 0
    mysql> insert into student values(1,'张三',20,'男',101);
    Query OK, 1 row affected (0.00 sec)

    image.gif

    上述代码我们先对classes表插入数据后,再才能对student表中插入相应的数据。因此一个表通过外键连接其他表时候,那么这个表(前者)就是那个表(后者)的子表。在上述两表中,student作为子表,classes作为父表,所以student表要插入数据必需先满足父表中的相应数据。这就是FOREIGN KEY的作用!

    image.gif编辑


    当然,我们删除这个两个表中的数据时候也是有先后顺序的,我们必须得先删子表再删父表。

    先删除父表中数据:

    mysql> delete from classes;
    ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`test`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`classes_id`) REFERENCES `classes` (`id`))

    image.gif

    提示了错误:ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`test`. `student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`classes_id`) REFERENCES `classes` (`id`)) 意为:错误1451(23000):不能删除或更新父行:外键约束失败(' test ')。 ' student ',约束' student_ibfk_1 '外键(' classes_id ')引用' classes ' (' id ')) RAIN

    当我们先删除子表中数据保证子表中没有数据关联父表时,这个时候就能删除父表中的数据了:

    mysql> delete from student;
    Query OK, 1 row affected (0.00 sec)
    mysql> delete from classes;
    Query OK, 3 rows affected (0.00 sec)

    image.gif

    可以看到上述代码正常的运行了,因此当我们想要设计复杂表结构时可以使用FOREIGN KEY这个外键约束。


    注意,MySQL中的sql语句或者任何字段大小写不敏感,也就是你可以大写也可以小写,因此博主在举例的时一时是小写一时是大写这个不必在意。其次在MySQL实际的开发中不建议轻易的删除数据库或者全列查询数据库这样的操作是很危险的,我们可以在日常的学习或练习过程中可以安心使用这些指令,到了开发的时候可不敢轻易删库查库。

    image.gif编辑

    本期博文到这里就结束了,感谢你的耐心阅读。码文不易,如有收获还请给博主点个小小的关注。

    相关实践学习
    如何快速连接云数据库RDS MySQL
    本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
    全面了解阿里云能为你做什么
    阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
    相关文章
    |
    1月前
    |
    数据采集 数据库 Python
    有哪些方法可以验证用户输入数据的格式是否符合数据库的要求?
    有哪些方法可以验证用户输入数据的格式是否符合数据库的要求?
    157 75
    |
    24天前
    |
    Java 关系型数据库 MySQL
    SpringBoot 通过集成 Flink CDC 来实时追踪 MySql 数据变动
    通过详细的步骤和示例代码,您可以在 SpringBoot 项目中成功集成 Flink CDC,并实时追踪 MySQL 数据库的变动。
    169 43
    |
    16天前
    |
    存储 SQL 关系型数据库
    MySQL底层概述—4.InnoDB数据文件
    本文介绍了InnoDB表空间文件结构及其组成部分,包括表空间、段、区、页和行。表空间是最高逻辑层,包含多个段;段由若干个区组成,每个区包含64个连续的页,页用于存储多条行记录。文章还详细解析了Page结构,分为通用部分(文件头与文件尾)、数据记录部分和页目录部分。此外,文中探讨了行记录格式,包括四种行格式(Redundant、Compact、Dynamic和Compressed),重点介绍了Compact行记录格式及其溢出机制。最后,文章解释了不同行格式的特点及应用场景,帮助理解InnoDB存储引擎的工作原理。
    MySQL底层概述—4.InnoDB数据文件
    |
    7天前
    |
    监控 关系型数据库 MySQL
    MySQL和SQLSugar百万条数据查询分页优化
    在面对百万条数据的查询时,优化MySQL和SQLSugar的分页性能是非常重要的。通过合理使用索引、调整查询语句、使用缓存以及采用高效的分页策略,可以显著提高查询效率。本文介绍的技巧和方法,可以为开发人员在数据处理和查询优化中提供有效的指导,提升系统的性能和用户体验。掌握这些技巧后,您可以在处理海量数据时更加游刃有余。
    36 9
    |
    2天前
    |
    SQL 数据建模 BI
    【YashanDB 知识库】用 yasldr 配置 Bulkload 模式作单线程迁移 300G 的业务数据到分布式数据库,迁移任务频繁出错
    问题描述 详细版本:YashanDB Server Enterprise Edition Release 23.2.4.100 x86_64 6db1237 影响范围: 离线数据迁移场景,影响业务数据入库。 外场将部分 NewCIS 的报表业务放到分布式数据库,验证 SQL 性能水平。 操作系统环境配置: 125G 内存 32C CPU 2T 的 HDD 磁盘 问题出现的步骤/操作: 1、部署崖山分布式数据库 1mm 1cn 3dn 单线启动 yasldr 数据迁移任务,设置 32 线程的 bulk load 模式 2、观察 yasldr.log 是否出现如下错
    |
    7天前
    |
    JSON Java 关系型数据库
    Hutool创建数据源工厂动态查询不同数据库不同数据表的数据
    Hutool创建数据源工厂动态查询不同数据库不同数据表的数据
    23 2
    |
    8天前
    |
    存储 关系型数据库 MySQL
    MySQL进阶突击系列(09)数据磁盘存储模型 | 一行数据怎么存?
    文中详细介绍了MySQL数据库中一行数据在磁盘上的存储机制,包括表空间、段、区、页和行的具体结构,以及如何设计和优化行数据存储以提高性能。
    |
    7天前
    |
    存储 SQL 关系型数据库
    【YashanDB 知识库】MySQL 迁移至崖山 char 类型数据自动补空格问题
    问题分类】功能使用 【关键字】char,char(1) 【问题描述】MySQL 迁移至崖山环境,字段类型源端和目标端都为 char(2),但应用存储的数据为'0'、'1',此时崖山查询该表字段时会自动补充空格 【问题原因分析】mysql 有 sql_mode 控制,检查是否启用了 PAD_CHAR_TO_FULL_LENGTH SQL 模式。如果启用了这个模式,MySQL 才会保留 CHAR 类型字段的尾随空格,默认没有启动。 #查看sql_mode mysql> SHOW VARIABLES LIKE 'sql_mode'; 【解决/规避方法】与应用确认存储的数据,正确定义数据
    |
    2月前
    |
    SQL 存储 运维
    从建模到运维:联犀如何完美融入时序数据库 TDengine 实现物联网数据流畅管理
    本篇文章是“2024,我想和 TDengine 谈谈”征文活动的三等奖作品。文章从一个具体的业务场景出发,分析了企业在面对海量时序数据时的挑战,并提出了利用 TDengine 高效处理和存储数据的方法,帮助企业解决在数据采集、存储、分析等方面的痛点。通过这篇文章,作者不仅展示了自己对数据处理技术的理解,还进一步阐释了时序数据库在行业中的潜力与应用价值,为读者提供了很多实际的操作思路和技术选型的参考。
    60 1
    |
    2月前
    |
    存储 Java easyexcel
    招行面试:100万级别数据的Excel,如何秒级导入到数据库?
    本文由40岁老架构师尼恩撰写,分享了应对招商银行Java后端面试绝命12题的经验。文章详细介绍了如何通过系统化准备,在面试中展示强大的技术实力。针对百万级数据的Excel导入难题,尼恩推荐使用阿里巴巴开源的EasyExcel框架,并结合高性能分片读取、Disruptor队列缓冲和高并发批量写入的架构方案,实现高效的数据处理。此外,文章还提供了完整的代码示例和配置说明,帮助读者快速掌握相关技能。建议读者参考《尼恩Java面试宝典PDF》进行系统化刷题,提升面试竞争力。关注公众号【技术自由圈】可获取更多技术资源和指导。

    热门文章

    最新文章