当前位置: 首页 > news >正文

mysql表的操作——mysql表的约束

文章目录

  • mysql表的约束
    • 表约束的基本认识
    • 表的相关约束
      • 空属性
      • 默认值
      • 列描述
      • zerofill
      • 主键
      • 自增长
      • 唯一键
      • 外键

mysql表的约束

本篇文章,我们将着重认识,在mysql中对于表的约束条件!

其实在讲mysql的数据类型的时候,就已经简单说过:
👉数据类型,本质上也是mysql对于表的约束!

表约束的基本认识

首先,我们还是需要对这个表的约束做一个基本的认识!

表的约束:
表中一定会有各种的约束:如数据类型,数据类型是否越界等…


基本思想:
mysql通过这些约束,能够倒逼程序员,要按照约束条件进行正确地数据插入!
在mysql看来:通过约束就能够保证,插入的数据符合约束条件,是合法的!

约束的最终目标 👉 保证插入的数据完整性和可预期性!
也就是说,从表中获取的数据,起码是可以预期到的!而不是不符合约束条件的值。

但是:还是要说的是 -> 约束条件只能保证数据的合法性与可预期性,但是无法保证正确性!

表的相关约束

对于表的约束,其实有很多:

null/not null,default, comment, zerofill,primary key,auto_increment,unique key…

我们这里挑选几个比较重要的来进行讲解!

空属性

在正式讲解空属性前,我们需要明白:

null''是不一样的!前者表示这一项为空(没有该项),后者表示有,但是内容是空串!

本质上是因为:在mysql中,null是不参与计算的:

mysql> select null-> ;
+------+
| NULL |
+------+
| NULL |
+------+
1 row in set (0.00 sec)mysql> select null + 1;
+----------+
| null + 1 |
+----------+
|     NULL |
+----------+
1 row in set (0.00 sec)

我们现在先创建一个表:(在id面带上not null,name后面带上null)
在这里插入图片描述
我们使用show create table t1来进行查看表的创建相关属性:

然后尝试插入一些数据:
在这里插入图片描述

我们发现:
全列插入是可行的,单纯插入名字也是可行的,但唯独单独插入id不行!

本质的原因是什么呢?
其实是因为,我们在建表的时候,对于id这一列的数据,设置了约束not null

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

我们通过查看表的结构可以发现,对于id字段,是不允许为空的
而如果我们不显示指定数据是否允许为空,mysql自动默认设置可以为空!

这就是mysql对于表的一种约束!要求某种数据不能为空!又或是默认为空!
如果设置了不为空,那么我们在获取该数据的时候,至少不会取出来为空的数据!

空属性其实很简单:
如果要设置不为空属性,只需要在数据的类型后面追加声明not null!
如果声明了null,或者说不声明,mysql的处理都是允许该字段为空。

默认值

默认值:关键字为default
我们对于默认值肯定是很熟悉的!比如c++内函数参数的缺省参数!其实也叫默认值。

在mysql中,是允许我们对于字段设置一个默认值的!
只不过,当我们不写任何默认值的时候,mysql的处理是defalut null:
在这里插入图片描述

也就是,默认值mysql都是处理为null的!
只不过如果设置了not null
就没有mysql自动处理的默认值!所以这就是为什么不能忽略该字段的数据的插入!

下面,我们就创建一个新的表,来测试一下默认值的属性:

mysql> create table stu(-> id int not null,-> gender char(2) default '男',-> telphone char(11) not null default '00000000000',-> class varchar(20) -> );
Query OK, 0 rows affected (0.02 sec)mysql> desc stu;
+----------+-------------+------+-----+-------------+-------+
| Field    | Type        | Null | Key | Default     | Extra |
+----------+-------------+------+-----+-------------+-------+
| id       | int         | NO   |     | NULL        |       |
| gender   | char(2)     | YES  |     ||       |
| telphone | char(11)    | NO   |     | 00000000000 |       |
| class    | varchar(20) | YES  |     | NULL        |       |
+----------+-------------+------+-----+-------------+-------+
4 rows in set (0.01 sec)

我们尝试插入一些数据进行测试:
在这里插入图片描述
我们来简单总结一下对于默认值的约束属性:

1.如果设置了默认值,mysql会采用用户输入的!反之default null
2.如果default和not null同时出现:

  • 因为not null -> mysql不会自动设置default null,所以该字段非空
  • 但因为用户显式指定了默认值,mysql使用了用户提供的默认值
  • 最终就导致,这一列是可以忽略插入的,mysql会使用默认值!

总结就是:只有设置了default的字段,才能忽略插入!
而系统默认自带默认值为空,所以默认允许我们忽略字段的插入!

列描述

列描述其实就是comment
它其实严格意义上来说,只有约束的名义,没有实际约束的操作!

它就很像是我们在写代码的时候的一些注释!
它并不会通过实际的一些操作来对表进行约束,它更多的作用是给数据库的使用者,或是DBA(database administrator),,数据库管理员进行了解数据用途的!

下面我们简单展示一下即可:

mysql> create table t2( id int not null comment '这是id', name varchar(20) default 'zhangsan' comment '这是姓名' );
Query OK, 0 rows affected (0.03 sec)mysql> desc t2;
+-------+-------------+------+-----+----------+-------+
| Field | Type        | Null | Key | Default  | Extra |
+-------+-------------+------+-----+----------+-------+
| id    | int         | NO   |     | NULL     |       |
| name  | varchar(20) | YES  |     | zhangsan |       |
+-------+-------------+------+-----+----------+-------+
2 rows in set (0.00 sec)mysql> show create table t2;
| t2    | CREATE TABLE `t2` (`id` int NOT NULL COMMENT '这是id',`name` varchar(20) COLLATE utf8mb4_general_ci DEFAULT 'zhangsan' COMMENT '这是姓名'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci       |

其实这个列描述根本就没有加入到表的结构内!
我们只能通过show create table table_name语句来查询到相关的列描述!

所以,这就是为什么上面说:

列描述只有约束的名义,但是没有约束的动作!
因为它的本质就是像注释,但在合理的情况下确实也起到了约束的作用!

zerofill

在讲解数据类型的时候,我们遗留了一个问题:

对于浮点数来说,或者字符串来说,声明类型的时候可以通过类型()语句:
通过括号内的设置来决定类型的大小或长短!

但是,我们可以发现,对于int来说,有时候也能够发现后序会有如int(11)的情况!
但是要说明的是:在mysql 8.0.17以上的版本是没有这个情况出现的!

我的mysql版本就是比较高的,所以我这里是显示不出来的!

ynp@hcss-ecs-1643:~$ mysql --version
mysql  Ver 8.0.43 for Linux on x86_64 (MySQL Community Server - GPL)

在旧版本下:
如果直接使用int,那么表中显示的是int(11)
如果使用int unsigned,那么表中显示的是int unsigned(10)


现在我们就基于旧版本的情况,来了解一下,对于整数类型括号内的数字是干什么的?

目前我们至少能够知道:它肯定不是指示大小的!

mysql> create table t3( a int(5) zerofill, b int(6) unsigned);
Query OK, 0 rows affected, 3 warnings (0.02 sec)mysql> desc t3;
+-------+--------------------------+------+-----+---------+-------+
| Field | Type                     | Null | Key | Default | Extra |
+-------+--------------------------+------+-----+---------+-------+
| a     | int(5) unsigned zerofill | YES  |     | NULL    |       |
| b     | int unsigned             | YES  |     | NULL    |       |
+-------+--------------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

我们先看现象,最后来解释是什么:

mysql> insert into t3(a, b) values (115, 12345678)-> ;
Query OK, 1 row affected (0.00 sec)mysql> insert into t3(a, b) values (1115, 12345678);
Query OK, 1 row affected (0.01 sec)mysql> insert into t3(a, b) values (11151, 12345678);
Query OK, 1 row affected (0.00 sec)mysql> insert into t3(a, b) values (11131251, 12345678);
Query OK, 1 row affected (0.01 sec)mysql> select * from t3;
+----------+----------+
| a        | b        |
+----------+----------+
|    00115 | 12345678 |
|    01115 | 12345678 |
|    11151 | 12345678 |
| 11131251 | 12345678 |
+----------+----------+
4 rows in set (0.00 sec)

我们可以发现,当我们对a的字段显示设置括号内的数字,并且使用zerofill对其约束:
读取数据的时候,a的长度是必须满足五位的(不足高位补0,足够正常显示!)

其实zerofill,从名字上来看:就是填充0
作用:使指定列的数字显示长度至少达到指定的长度!超出则不管。

一些细节部分:

  1. MySQL 8.0+ 的优化行为:
    如果不需要 ZEROFILL,可以忽略显示宽度,它不影响实际数据存储。
  2. zerofill字段只能给整数使用!

该字段就是对数据进行格式化控制的!只有显示的时候是这么长,筛选,使用的时候不是:

mysql> select * from t3;
+----------+----------+
| a        | b        |
+----------+----------+
|    00115 | 12345678 |
|    01115 | 12345678 |
|    11151 | 12345678 |
| 11131251 | 12345678 |
+----------+----------+
4 rows in set (0.00 sec)mysql> select * from t3 where a=115;
+-------+----------+
| a     | b        |
+-------+----------+
| 00115 | 12345678 |
+-------+----------+
1 row in set (0.00 sec)mysql> select hex(a) from t3;
+--------+
| hex(a) |
+--------+
| 73     |
| 45B    |
| 2B8F   |
| A9D973 |
+--------+
4 rows in set (0.00 sec)

我们可以很清晰的发现,不管是使用where筛选,还是使用hex函数显示十六进制:
我们都是不需要使用指定的长度的数字来进行操作的!使用原数字即可!
(内部存储是正常的,只不过因为zerofill的约束,使得显示的时候做格式化控制。)


但是现在还需要解决最后一个细节:
即为什么在mysql 8.0以下的版本:默认int(11),int(10) unsigned呢?

我们根据zerofill的约束理解,我们知道该字段就是用来填充格式的!(不足高位补0)

int存储范围​​:-2,147,483,648 到 2,147,483,647(即 ​​-2³¹ ~ 2³¹-1​​)
unsigned int存储范围​​:0到 4,294,967,295(即 ​​0 ~ 2³²-1​​)

我们发现,不管是int还是unsigned int,数据最长也就是10位数!
但是对于int来说,需要多一位来表示符号位! -> 所以int的默认显示宽度为11!

主键

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

首先我们需要弄明白:主键能用来做什么?
我们学过哈希表,我们管unordered_map内存储的内容是键值对(key, value)!

主键其实作用就和哈希中的Key是类似的,就是一个索引的基准值!(在一张表内不能重复!)

需要使用主键的时候,只需要在建表的时候声明以下primary key即可!

mysql> create table t4 (id int primary key, name varchar(20));
Query OK, 0 rows affected (0.03 sec)mysql> desc t4;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int         | YES   | PRI | NULL    |       |
| name  | varchar(20) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

然后查询表的结构,可以发现,被设置主键的字段,Key的位置会带上PRI标志!

查询表的创建:

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

我们发现,mysql确实设置了对应的主键!PRIMARY KEY ('id')!且不会在变量后面跟着!
最重要的是,一旦设置主键,mysql自动为其补上not null!

下面尝试插入一些数据:
在这里插入图片描述

我们发现,一旦设置了主键:
就不能忽略插入,也不能插入null,更不能重复插入了!

因为主键的功能:就是要保证该字段的内容,在表内是具有唯一性质的!


当然,主键是可以后续追加或者删除的!

删除主键:alter table table_name drop primary key
在这里插入图片描述
因为mysql知道主键是谁,所以直接说删除主键即可,不需要指明主键是哪一列。

添加主键:alter table table_name add primary key(字段列表)
在这里插入图片描述


前面说:一张表只能有一个主键,但是不代表逐渐内只有一列!
如果说,我们今天并不是想以某个单一的字段作为主键,也是可以声明复合键的:

mysql> create table person(-> uid int,-> name varchar(20),-> tel varchar(11),-> job char(10),-> primary key(uid, name)-> );
Query OK, 0 rows affected (0.03 sec)mysql> desc person;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| uid   | int         | NO   | PRI | NULL    |       |
| name  | varchar(20) | NO   | PRI | NULL    |       |
| tel   | varchar(11) | YES  |     | NULL    |       |
| job   | char(10)    | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)mysql> show create table person \G;
*************************** 1. row ***************************Table: person
Create Table: CREATE TABLE `person` (`uid` int NOT NULL,`name` varchar(20) COLLATE utf8mb4_general_ci NOT NULL,`tel` varchar(11) COLLATE utf8mb4_general_ci DEFAULT NULL,`job` char(10) COLLATE utf8mb4_general_ci DEFAULT NULL,PRIMARY KEY (`uid`,`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci
1 row in set (0.00 sec)

我们发现:确实是可以以多列合并作为一个主键的!
只不过声明方式是需要另起一行,说明复合主键由哪些字段构成!

在这里插入图片描述
经过一番数据插入的测试,对于复合主键可以得到以下结论:

1.复合主键中的多个字段,每一个都不能为空!
2.复合主键的唯一性是指:对复合主键内的字段全都相同!只要有一个不同就是不同的!

这其实也就是一个主键!只不过这个主键是以多个字段的情况来进行判断的!
其实也是对表做了一定的约束!要求插入的数据,在(id, name)这两个字段上不能完全重复!

自增长

auto_increment:当对应的字段,不给值,会自动的被系统触发,系统会从当前字段中已经有的最大值+1操作,得到一个新的不同的值。通常和主键搭配使用,作为逻辑主键。

注意:auto_increment只能是整数字段才能使用!且auto_increment和default不能同时设置!
(因为auto_increment是要给对应字段设置一个值的,default也是,二者存在冲突!)

mysql> create table t5(id int not null default 1 auto_increment, name varchar(20) );
ERROR 1067 (42000): Invalid default value for 'id'

还有就是:如果要自增长,它必须是一个键!(可以不是主键!后序会说)
(之不过一般来说,auto_increment是配合着primary key使用的!)

mysql> create table t5(id int not null  auto_increment, name varchar(20) );
ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key

建立一个带有自增长字段的表:

mysql> create table t5(id int not null primary key auto_increment, name varchar(20) );
Query OK, 0 rows affected (0.03 sec)mysql> desc t5;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int         | NO   | PRI | NULL    | auto_increment |
| name  | varchar(20) | YES  |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.01 sec)mysql> show create table t5 \G;
*************************** 1. row ***************************Table: t5
Create Table: CREATE TABLE `t5` (`id` int NOT NULL AUTO_INCREMENT,`name` varchar(20) COLLATE utf8mb4_general_ci DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci
1 row in set (0.01 sec)

我们尝试插入一些值:
在这里插入图片描述
第一次的值一旦我们指定好后(也可以不插入该字段,让mysql自行指定默认值):‘
下一次开始mysql自动会记录AUTO_INCREMENT的值:即下一次插入该字段的默认值!

如果我们再随便插入一个数据:
在这里插入图片描述
我们发现,下一次的AUTO_INCREMENT = 6,也就是说:
AUTO_INCREMENT是按照当前表中:该字段的最大值+1进行设置的!

唯一键

在mysql中,是不可能只有一个字段是需要作为唯一值的。
就拿我们人来说:身份证是唯一值,但是我们的电话号码也是唯一值啊!

但是,mysql又规定,一张表中只能有一个主键!这该怎么办呢?

注意:这里绝对不能使用复合主键!
我们这里要求的是:两个字段都需要唯一!但是复合主键只要有一个字段不一样就可以插入!

所以,基于此要求:
mysql提供了另外一种键!即唯一键:unique(简写)!

mysql> create table person(-> id int primary key,-> name varchar(20),-> tel char(11) unique,-> job char(10)-> );
Query OK, 0 rows affected (0.03 sec)mysql> desc person;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int         | NO   | PRI | NULL    |       |
| name  | varchar(20) | YES  |     | NULL    |       |
| tel   | char(11)    | YES  | UNI | NULL    |       |
| job   | char(10)    | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)

我们可以发现,设置了唯一键的字段,在Key状态下显示UNI

尝试插入一些数据进行测试:
在这里插入图片描述
我们发现,其实唯一键和主键的用法类似!只不过说在于:

当唯一键字段有默认值(甚至为空)时,是可以进行忽略该字段的插入的!这点主键不行。

其余的用法差不多:也是在表中只能出现一次的!即该字段不能出现重复的值!


现在我们就需要理解:
主键和唯一键的区别是什么?它们仅仅是在插入值能否为空上有一些区别!

我们可以简单理解成,主键更多的是标识唯一性的。而唯一键更多的是保证在业务上,不要和别的信息出现重复。乍一听好像没啥区别,我们举一个例子

其实我们给唯一键设置上not null,其实和主键就在使用上就没有区别了!
主键大部分情况下,是选择一些和业务无关的字段!以便后序进行快速搜索的。

外键

外键用于定义主表和从表之间的关系:外键约束主要定义在从表上,主表则必须是有主键约束或unique约束。当定义外键后,要求外键列数据必须在主表的主键列存在或为null。

mysql是一种关系型数据库,数据库和数据库之间是会存在一些关系的:

比如:
现在我们有一个表,专门描述的是学校内班级编号和班级名称的关系!
然后,我们需要管理学生(学号、姓名、班级…)

我们当然可以一股脑地把所有信息塞到一张表:
但是,如果这样做,会导致表内一些列项会异常的冗余(入班级编号、名称)

所以,此时我们可以这样做:
在这里插入图片描述

我们让一张表记录学生的姓名、学号,和班级的id。另一张表记录班级名称和id的映射关系!

这样子,两张表在stu->class_id和班级表myclass->id是形成了约束关系的!
(此时很明显,stu表是依附于myclass表的!)
我们规定:

当stu内尝试插入新数据时,需判断class_id是否已存在于班级表?(业务上不允许不存在的班级出现)
当myclass删除数据时,需判断stu内是否还存有该字段的数据?如果有是不能删除的!

但是,仅仅是创建这两张表也是没有用的!因为只有约束之名,没有约束之实!
还必须要通过一定的技术手段来实现,两个表之间的约束!

创建外键的语法:
foreign key(该表内的列) references 主表(主表的列)

mysql> create table myclass(-> id int primary key,-> name varchar(20)-> );
Query OK, 0 rows affected (0.03 sec)mysql> create table student(-> id int primary key,-> name varchar(20),-> class_id int,-> foreign key(class_id) references myclass(id)-> );
Query OK, 0 rows affected (0.03 sec)mysql> desc myclass;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int         | NO   | PRI | NULL    |       |
| name  | varchar(20) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)mysql> desc student;
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| id       | int         | NO   | PRI | NULL    |       |
| name     | varchar(20) | YES  |     | NULL    |       |
| class_id | int         | YES  |     | NULL    |       |
+----------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

现在我们先向班级表中分别添加一些数据:

mysql> insert into myclass values (1, '高三一班');
Query OK, 1 row affected (0.01 sec)mysql> insert into myclass values (2, '高三二班');
Query OK, 1 row affected (0.01 sec)

我们尝试插入不存在主表的数据,发现是插入失败的!
在这里插入图片描述

我们尝试删除主表中的一些数据:
在这里插入图片描述
我们发现:想要删除主表的数据,比如得保证该数据在从表中是没有的!否则无法删除!

所以,最后我们就知道了,在mysql中如何使用外键来对两个表进行约束!

http://www.dtcms.com/a/470903.html

相关文章:

  • 城关区建设局网站吉林从业自助app下载
  • 网站域名类型wordpress获取权限
  • VxLAN解析
  • 口碑好网站建设公司哪家好网站是做排行榜
  • 张掖网站建设网页设计心得体会400字
  • 【优选算法必刷100题】第011~012题(滑动窗口):最大连续1的个数 III,将 x 减到 0 的最小操作数
  • seochinaz查询seo排名优化公司哪家好
  • 一场跨越技术栈的诡异异常侦破记
  • 基于之前说麦克斯韦方程的挠场和涡旋场和特斯拉的非赫兹波
  • 铁路项目建设 网站wordpress站点
  • i.mx8上Qt应用星期显示异常
  • 08_Matplotlib数据可视化
  • 怎么上传自己做的网站wordpress注册跳转
  • 荆州做网站建设学校网站多钱
  • RDKit | 深入探讨用于捕获立体化学特征的分子指纹
  • Windows Server 2019域域控制器如何设置编辑WMI筛选器
  • Hive SQL:where 与 having(城市分组,年龄筛选)
  • C# 枚举(Enum)
  • 松江网站建设哪家好手机网站开发计划
  • 模板网站如何做seo网站维护html模板
  • PostgreSql 判断字符串是否为null 或 空字符串
  • 我做外贸要开国际网站吗个人网站cms
  • VR全景园区完整实现方案
  • GPS与北斗组合单点定位算法MATLAB实现
  • PostgreSQL 中 CTE 的使用
  • 网站开发语言怎么样wordpress底板版权
  • 【C语言加油站】C语言文件操作详解:从“流”的概念到文件的打开与关闭​
  • 涪陵网站建设公司国内可以上的网站
  • 国产CAD皇冠CAD(CrownCAD)三维建模教程:变压器
  • 网站博客程序logo智能设计一键生成器