【MySQL】表的约束(上)详解

📢博客主页:https://blog.csdn.net/2301_779549673

📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!

📢本文由 JohnKi 原创,首发于 CSDN🙉

📢未来很长,值得我们全力奔赴更美好的生活✨

文章目录

  • 📢前言
  • [🏳️‍🌈1、空属性 - NULL](#🏳️‍🌈1、空属性 - NULL)
  • [🏳️‍🌈2、默认值 - DEFAULT](#🏳️‍🌈2、默认值 - DEFAULT)
  • [🏳️‍🌈3、列描述 - comment](#🏳️‍🌈3、列描述 - comment)
  • [🏳️‍🌈4、 zerofill - 显示数值时用零(0)填充到列定义的显示宽度](#🏳️‍🌈4、 zerofill - 显示数值时用零(0)填充到列定义的显示宽度)
  • [🏳️‍🌈5、主键 - primary key](#🏳️‍🌈5、主键 - primary key)
  • 👥总结

📢前言

表的约束 :表中一定要有各种约束,通过约束,让我们未来插入数据库表中的教据是符合预期的。约束本质是通过技术手段,倒通程序员,插入正确的数据。反过来,站在mysql的视角,凡是插入进来的数据,都是符合数据约束的!

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

真正约束字段的是数据类型,但是数据类型约束很单一,需要有一些额外的约束,更好的保证数据的合法性,从业务逻辑角度保证数据的正确性。比如有一个字段是email,要求是唯一的。

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


🏳️‍🌈1、空属性 - NULL

两个值: null (默认的) 和 not null (不为空)

数据库默认字段都是字段为空,但是实际开发时,尽可能保证字段不为空,因为数据为空没办法参与运算。

案例:

创建一个班级表,包含班级名和班级所在的教室。

站在正常的业务逻辑中:

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

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

就是"约束"。

cpp 复制代码
mysql> create table if not exists myclass(
    -> class_name varchar(20) not null,
    -> class_room varchar(20) not null,
    -> other varchar(20)
    -> );
Query OK, 0 rows affected (0.02 sec)

mysql> desc myclass;
+------------+-------------+------+-----+---------+-------+
| Field      | Type        | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| class_name | varchar(20) | NO   |     | NULL    |       |
| class_room | varchar(20) | NO   |     | NULL    |       |
| other      | varchar(20) | YES  |     | NULL    |       |
+------------+-------------+------+-----+---------+-------+
3 rows in set (0.01 sec)

NULL列表示的就是这一列的空属性,默认为空,加上 not null 就不为空

  1. 先按正常逻辑插入一行完整的数据
cpp 复制代码
mysql> insert into myclass (class_name, class_room, other) values ('高三2班', '101教室', '普通班');
Query OK, 1 row affected (0.00 sec)

mysql> select* from myclass;
+------------+------------+-----------+
| class_name | class_room | other     |
+------------+------------+-----------+
| 高三2班    | 101教室    | 普通班    |
+------------+------------+-----------+
1 row in set (0.00 sec)

顺利插入,并打印出来了

  1. 试试 other 字段不插入
cpp 复制代码
mysql> insert into myclass (class_name, class_room) values ('高三3班', '103教室');
Query OK, 1 row affected (0.01 sec)

mysql> select * from myclass;
+------------+------------+-----------+
| class_name | class_room | other     |
+------------+------------+-----------+
| 高三2班    | 101教室    | 普通班    |
| 高三3班    | 103教室    | NULL      |
+------------+------------+-----------+
2 rows in set (0.00 sec)

顺利插入,且无影响,不过 other 字段为空

  1. 试试 not null 属性字段不插入
cpp 复制代码
mysql> insert into myclass (class_name) values ('高三4班');
ERROR 1364 (HY000): Field 'class_room' doesn't have a default value
mysql> insert into myclass (class_name, class_room) values ('高三4班', null);
ERROR 1048 (23000): Column 'class_room' cannot be null
mysql> insert into myclass (class_name, class_room) values (null, null);
ERROR 1048 (23000): Column 'class_name' cannot be null

可见,对于if not null 属性的字段,不论是不插入任何数据,还是把插入数据设为 null ,都无法成功插入

🏳️‍🌈2、默认值 - DEFAULT

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

用户可以选择性的使用默认值。

假设有一个相亲网站,年龄默认 18 , 性别默认 男

cpp 复制代码
mysql> create table if not exists t13(
    -> name varchar(20) not null,
    -> age tinyint unsigned default 18,
    -> gender char(1) default '男'
    -> );
Query OK, 0 rows affected (0.01 sec)

mysql> desc t13;
+--------+---------------------+------+-----+---------+-------+
| Field  | Type                | Null | Key | Default | Extra |
+--------+---------------------+------+-----+---------+-------+
| name   | varchar(20)         | NO   |     | NULL    |       |
| age    | tinyint(3) unsigned | YES  |     | 18      |       |
| gender | char(1)             | YES  |     | 男      |       |
+--------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
  1. 先试试是否有用
cpp 复制代码
mysql> insert into t13(name, age, gender) values('张三', 19, '男');
Query OK, 1 row affected (0.01 sec)

mysql> select * from t13;
+--------+------+--------+
| name   | age  | gender |
+--------+------+--------+
| 张三   |   19 | 男     |
+--------+------+--------+
1 row in set (0.00 sec)

有效!

  1. 插入一行只有姓名的数据
cpp 复制代码
mysql> insert into t13 (name) values('李四');
Query OK, 1 row affected (0.01 sec)

mysql> select * from t13;
+--------+------+--------+
| name   | age  | gender |
+--------+------+--------+
| 张三   |   19 | 男     |
| 李四   |   18 | 男     |
+--------+------+--------+
2 rows in set (0.00 sec)

成功补齐了默认值

可以得出结论,default:如果设置了,用户将来插入,有具体的数据,就用用户的,没有就用默认的

  1. 倘若当前值为 Not null 并且还有默认值时
cpp 复制代码
mysql> create table if not exists t14(
    -> name varchar(20) not null,
    -> age tinyint default 18,
    -> gender char(1) not null default '男'
    -> );
Query OK, 0 rows affected (0.02 sec)

mysql> desc t14;
+--------+-------------+------+-----+---------+-------+
| Field  | Type        | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| name   | varchar(20) | NO   |     | NULL    |       |
| age    | tinyint(4)  | YES  |     | 18      |       |
| gender | char(1)     | NO   |     | 男      |       |
+--------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql> show create table t14;
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                        |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t14   | CREATE TABLE `t14` (
  `name` varchar(20) NOT NULL,
  `age` tinyint(4) DEFAULT '18',
  `gender` char(1) NOT NULL DEFAULT '男'
) ENGINE=InnoDB DEFAULT CHARSET=utf8  |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

插入一行数据试试

cpp 复制代码
mysql> insert into t14 (age, gender) values(20, '男');
ERROR 1364 (HY000): Field 'name' doesn't have a default value
mysql> insert into t14 (name, age, gender) values('张三', 20, '男');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t14 (name, gender) values('赵六', '女');
Query OK, 1 row affected (0.01 sec)

mysql> select * from t14;
+--------+------+--------+
| name   | age  | gender |
+--------+------+--------+
| 张三   |   20 | 男     |
| 赵六   |   18 | 女     |
+--------+------+--------+
2 rows in set (0.00 sec)

可见,

  • 如果我们没有明确指定一列要插入,用的是default,如果建表中,对应列默认没有设置default值,无法直接插入
  • default和NOTNULL不冲突,而是互相补充的

🏳️‍🌈3、列描述 - comment

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

来进行了解。

cpp 复制代码
mysql> create table if not exists t16(
    -> name varchar(20) not null comment '这个是用户的用户名',
    -> age tinyint unsigned default 18 comment '这个是用户的年龄',
    -> gender char(1) default '男' comment '这个是用户的性别'
    -> );
Query OK, 0 rows affected (0.03 sec)

mysql> desc t16;
+--------+---------------------+------+-----+---------+-------+
| Field  | Type                | Null | Key | Default | Extra |
+--------+---------------------+------+-----+---------+-------+
| name   | varchar(20)         | NO   |     | NULL    |       |
| age    | tinyint(3) unsigned | YES  |     | 18      |       |
| gender | char(1)             | YES  |     | 男      |       |
+--------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql> show create table t16;
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                                                                                                    |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t16   | CREATE TABLE `t16` (
  `name` varchar(20) NOT NULL COMMENT '这个是用户的用户名',
  `age` tinyint(3) unsigned DEFAULT '18' COMMENT '这个是用户的年龄',
  `gender` char(1) DEFAULT '男' COMMENT '这个是用户的性别'
) ENGINE=InnoDB DEFAULT CHARSET=utf8                           |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> insert into t16 (name, age, gender) values ('张三', 122, '男');
Query OK, 1 row affected (0.00 sec)

mysql> select * from t16;
+--------+------+--------+
| name   | age  | gender |
+--------+------+--------+
| 张三   |  122 | 男     |
+--------+------+--------+
1 row in set (0.00 sec)

能正常插入,但是一般不能通过 desc 查看注释信息,需要通过 show 查看

🏳️‍🌈4、 zerofill - 显示数值时用零(0)填充到列定义的显示宽度

ZEROFILLMySQL 数据库中的一个属性,主要用于数值类型的列(如INT、BIGINT等)。当在列定义中使用 ZEROFILL 属性时,它会使 MySQL 在显示数值时用零(0)填充到列定义的显示宽度。

cpp 复制代码
mysql> create table if not exists t17(
    -> a int unsigned not null,
    -> b int unsigned not null
    -> );
Query OK, 0 rows affected (0.02 sec)

mysql> desc t17;
+-------+------------------+------+-----+---------+-------+
| Field | Type             | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| a     | int(10) unsigned | NO   |     | NULL    |       |
| b     | int(10) unsigned | NO   |     | NULL    |       |
+-------+------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

mysql> show create table t17;
+-------+----------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                               |
+-------+----------------------------------------------------------------------------------------------------------------------------+
| t17   | CREATE TABLE `t17` (
  `a` int(10) unsigned NOT NULL,
  `b` int(10) unsigned NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+----------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

插入数据看看

cpp 复制代码
mysql> insert into t17 (a, b) values (2, 3);
Query OK, 1 row affected (0.00 sec)

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

能正常显示

为 b 字段设置 zerofill 属性

cpp 复制代码
mysql> alter table t17 modify b int unsigned zerofill;
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc t17;
+-------+---------------------------+------+-----+---------+-------+
| Field | Type                      | Null | Key | Default | Extra |
+-------+---------------------------+------+-----+---------+-------+
| a     | int(10) unsigned          | NO   |     | NULL    |       |
| b     | int(10) unsigned zerofill | YES  |     | NULL    |       |
+-------+---------------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

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

b 字段多了 zerofill 属性,数据也补齐到了10位

这次可以看到b的值由原来的3变成0000000003,这就是zerofill属性的作用,如果宽度小于设定的宽度,自动填充0。要注意的是,这只是最后显示的结果,在MySQL中实际存储的还是1。

🏳️‍🌈5、主键 - primary key

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

cpp 复制代码
mysql> create table if not exists test_key(
    -> id int unsigned primary key,
    -> name varchar(20) not null
    -> );
Query OK, 0 rows affected (0.02 sec)

mysql> desc test_key;
+-------+------------------+------+-----+---------+-------+
| Field | Type             | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| id    | int(10) unsigned | NO   | PRI | NULL    |       |
| name  | varchar(20)      | NO   |     | NULL    |       |
+-------+------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

mysql> show create table test_key\G
*************************** 1. row ***************************
       Table: test_key
Create Table: CREATE TABLE `test_key` (
  `id` int(10) unsigned NOT NULL,
  `name` varchar(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

插入两个主键值相同的数据试试

cpp 复制代码
mysql> insert into test_key values(1, '张飞');
Query OK, 1 row affected (0.01 sec)

mysql> select * from test_key;
+----+--------+
| id | name   |
+----+--------+
|  1 | 张飞   |
+----+--------+
1 row in set (0.00 sec)

mysql> insert into test_key values(1, '刘备');
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'

失败了

主键还能作为坐标进行增删查改

cpp 复制代码
mysql> insert into test_key values(2, '刘备');
Query OK, 1 row affected (0.01 sec)

mysql> select * from test_key;
+----+--------+
| id | name   |
+----+--------+
|  1 | 张飞   |
|  2 | 刘备   |
+----+--------+
2 rows in set (0.00 sec)

mysql> update test_key set name='曹操' where id = 2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from test_key;
+----+--------+
| id | name   |
+----+--------+
|  1 | 张飞   |
|  2 | 曹操   |
+----+--------+
2 rows in set (0.00 sec)

👥总结


本篇博文对 【MySQL】表的约束(上) 做了一个较为详细的介绍,不知道对你有没有帮助呢

觉得博主写得还不错的三连支持下吧!会继续努力的~

相关推荐
Dwyane037 分钟前
Android 车载虚拟化底层技术-Kernel 5.15 -Android13(multi-cards)技术实现
android·gitee
涛粒子34 分钟前
Redis 生产问题(重要)
数据库·redis·缓存
勿栀枝39 分钟前
sql多表联查图文
数据库·sql
LaLaLa_OvO2 小时前
ORACLE SQL思路: 多行数据有相同字段就合并成一条数据 分页展示
数据库·sql·oracle
晴天Y282 小时前
源码编译安装MySQL
数据库·mysql
一峰说2 小时前
数据分析PowerBI累积同比图
android·数据分析·powerbi
fmc1211042 小时前
【1】数据分析基础(一些概念)
服务器·数据库·oracle
时之彼岸Φ2 小时前
操作系统:文件系统
运维·数据库
With Order @!1472 小时前
如何在项目中使用人大金仓替换mysql
数据库·mysql
散修-小胖子3 小时前
MySQL常用运维操作(一):快速复制一张表
数据库·mysql