【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】表的约束(上) 做了一个较为详细的介绍,不知道对你有没有帮助呢

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

相关推荐
倔强的石头_2 小时前
kingbase备份与恢复实战(二)—— sys_dump库级逻辑备份与恢复(Windows详细步骤)
数据库
阿巴斯甜8 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker8 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq95279 小时前
Andorid Google 登录接入文档
android
黄林晴10 小时前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab1 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿1 天前
Android MediaPlayer 笔记
android
Jony_1 天前
Android 启动优化方案
android
阿巴斯甜1 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇1 天前
AOSP15 Input专题InputReader源码分析
android