📢博客主页: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
, zerofill
,primary key
,auto_increment
,unique 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
就不为空
- 先按正常逻辑插入一行完整的数据
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)
顺利插入,并打印出来了
- 试试 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
字段为空
- 试试 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)
- 先试试是否有用
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)
有效!
- 插入一行只有姓名的数据
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:如果设置了,用户将来插入,有具体的数据,就用用户的,没有就用默认的
- 倘若当前值为 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)填充到列定义的显示宽度
ZEROFILL
是 MySQL
数据库中的一个属性,主要用于数值类型的列(如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】表的约束(上) 做了一个较为详细的介绍,不知道对你有没有帮助呢
觉得博主写得还不错的三连支持下吧!会继续努力的~