【MySQL】表的约束

文章目录

  • 一、为什么要有约束
  • 二、非空约束
  • 三、默认值default约束
  • 四、列描述
  • 五、zerofill
  • 六、主键约束
    • 6.1 创建带有主键的表
    • 6.2 主键列不允许重复
    • 6.3 修改主键信息
    • 6.4 复合主键
  • 七、自增长
    • 7.1 创建自增长的主键
    • 7.2 连续插入数据
    • 7.3 创建表时设置自增长起始值
    • 7.4 获取最后一次自增长的值
  • 八、唯一键约束
    • 8.1 唯一键和主键的区别
    • 8.2 唯一键加上非空约束
  • 九、外键约束
    • 9.1 建立外键约束
    • 9.2 向从表里插入数据
    • 9.3 主表删除数据

一、为什么要有约束

约束是为了更好的保证数据的合法性,如果没有约束,我们可能在年龄字段填写个男,在性别字段填写个18。
通过约束,倒逼程序员插入数据库表中的数据符合预期。

二、非空约束

两个值:null(默认的)和not null(不为空)
数据库默认字段基本都是字段为空,但是实际开发时,尽可能保证字段不为空,因为数据为空没办法参与运算。

MySQL中的NULL代表什么都没有。
MySQL中的''代表空串

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

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.04 sec)

【MySQL】表的约束_第1张图片
这就表示插入的时候class_nameclass_room不能为空。

mysql> insert into myclass (class_name, class_room, other) values('大一', '101', '普通');
Query OK, 1 row affected (0.00 sec)

mysql> insert into myclass (class_name, class_room) values('大二', '102');
Query OK, 1 row affected (0.01 sec)
mysql> insert into myclass (class_name) values('大三');
ERROR 1364 (HY000): Field 'class_room' doesn't have a default value
mysql> insert into myclass (class_name) values('大三', NULL);
ERROR 1136 (21S01): Column count doesn't match value count at row 1

【MySQL】表的约束_第2张图片
如果没有非空约束且不插入数据默认为NULL。

三、默认值default约束

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

创建表:

mysql> create table t9(
    -> name varchar(20) not null,
    -> age tinyint unsigned default 18,
    -> gender char(1) default '男'
    -> );
Query OK, 0 rows affected (0.03 sec)

【MySQL】表的约束_第3张图片
插入数据:

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

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

可以看到如果设置了默认值并且没填写,默认为设置的default值。
当然如果设置了not noll并且没有设置default并且没有插入数据就会报错。

  • 如果既使用not null又使用default呢?
mysql> create table t10(
    -> name varchar(20) not null,
    -> age tinyint(4),
    -> gender char(1) not null default '男'
    -> );
Query OK, 0 rows affected (0.04 sec)

可以看到不冲突,可以理解为既然有了缺省值那么一定不会为NULL。

mysql> insert into t10 (name, age) values('李四', 20);
Query OK, 1 row affected (0.01 sec)

mysql> insert into t10 (name) values('李四');
Query OK, 1 row affected (0.00 sec)

【MySQL】表的约束_第4张图片
not null和defalut一般不需要同时出现,因为default本身有默认值,不会为空

如果我们在创建表的时候没有对字段设置为not null,也没有设置为default,那么该字段默认default null。

四、列描述

列描述:comment,没有实际含义,专门用来描述字段,会根据表创建语句保存,用来给程序员或DBA来进行了解。
类似于我们平时写的注释。

mysql> create table t11(
    -> name varchar(20) not null comment '用户名'
    -> );
Query OK, 0 rows affected (0.04 sec)

【MySQL】表的约束_第5张图片

五、zerofill

整型字段有个zerofill属性,在数字长度不够的数据前面填充0,以达到设定的长度。

mysql> create table t12(
    -> a int not null,
    -> b int unsigned not null
    -> );
Query OK, 0 rows affected (0.04 sec)

【MySQL】表的约束_第6张图片
有符号int圆括号中的数字为11,无符号int圆括号中的数字为10。这是因为有符号int其中一位是符号位。

插入数据:

mysql> insert into t12 values (1, 2);
Query OK, 1 row affected (0.00 sec)

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

此时添加zerofill属性:

mysql> alter table t12 modify b int unsigned zerofill;
Query OK, 0 rows affected (0.09 sec)
Records: 0  Duplicates: 0  Warnings: 0
mysql> select * from t12;
+---+------------+
| a | b          |
+---+------------+
| 1 | 0000000002 |
+---+------------+
1 row in set (0.00 sec)

再次插入数据:

mysql> insert into t12 values (100, 200);
Query OK, 1 row affected (0.00 sec)

mysql> select * from t12;
+-----+------------+
| a   | b          |
+-----+------------+
|   1 | 0000000002 |
| 100 | 0000000200 |
+-----+------------+
2 rows in set (0.00 sec)

如果int后边的圆括号是10并且设置了zerofill属性,那么一定会补齐到10位。

这样该列就是等宽的。
比如现在有200个班级,编号从001-200开始,那么创建表时将字段设置为int(3) unsigned或者int(4)就行了。

所以可以看出zerofill的作用就是格式化输出。

还有一点要注意如果括号里面设置的是4,但是位数超过了4位并且设置了zerofill属性那么就会按照数据本身显示。

六、主键约束

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

6.1 创建带有主键的表

mysql> create table test_key(
    -> id int unsigned primary key comment '学号',
    -> name varchar (20) not null
    -> );
Query OK, 0 rows affected (0.03 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)

可以看到主键自动携带非空约束。

6.2 主键列不允许重复

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

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

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

主键的作用就是保证了记录的唯一性。

mysql> select * from test_key where id=1;
+----+--------+
| id | name   |
+----+--------+
|  1 | 张三   |
+----+--------+
1 row in set (0.01 sec)

6.3 修改主键信息

  • 去掉主键约束
mysql> alter table test_key drop primary key;
Query OK, 2 rows affected (0.11 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> desc test_key;
+-------+------------------+------+-----+---------+-------+
| Field | Type             | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| id    | int(10) unsigned | NO   |     | NULL    |       |
| name  | varchar(20)      | NO   |     | NULL    |       |
+-------+------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
  • 增加主键约束
mysql> alter table test_key add primary key(id);
Query OK, 0 rows affected (0.10 sec)
Records: 0  Duplicates: 0  Warnings: 0

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)

6.4 复合主键

在创建表的时候,在所有字段之后,使用primary key(主键字段列表)来创建主键,如果有多个字段作为主键,可以使用复合主键。

mysql> create table t13(
    -> a int,
    -> b int,
    -> c int,
    -> primary key(a,b)
    -> );
Query OK, 0 rows affected (0.03 sec)

mysql> desc t13;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| a     | int(11) | NO   | PRI | NULL    |       |
| b     | int(11) | NO   | PRI | NULL    |       |
| c     | int(11) | YES  |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
3 rows in set (0.00 sec)

这个表还是只有一个主键,之不过a和b共同构成了一个主键

mysql> insert into t13 values (1, 2, 3);
Query OK, 1 row affected (0.01 sec)

mysql> insert into t13 values (1, 1, 3);
Query OK, 1 row affected (0.01 sec)

mysql> insert into t13 values (2, 2, 3);
Query OK, 1 row affected (0.00 sec)

mysql> insert into t13 values (1, 2, 4);
ERROR 1062 (23000): Duplicate entry '1-2' for key 'PRIMARY'

这里a和b不能完全一样。也就是只有a和b同时和历史数据冲突了才会出现主键冲突。

七、自增长

auto_increment:每次插入新数据的时候,被设置为自增长的字段的值每次会+1。通常和主键搭配使用,作为逻辑主键。

自增长的特点:

  • 任何一个字段要做自增长,前提是本身是一个索引(key一栏有值)
  • 自增长字段必须是整数
  • 一张表最多只能有一个自增长

7.1 创建自增长的主键

mysql> create table t14( 
    -> a int primary key auto_increment, 
    -> b varchar(10) not null 
    -> );
Query OK, 0 rows affected (0.04 sec)

mysql> desc t14;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| a     | int(11)     | NO   | PRI | NULL    | auto_increment |
| b     | varchar(10) | NO   |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

7.2 连续插入数据

mysql> insert into t14 (b) values ('good');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t14 (b) values ('yes');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t14 (b) values ('hello');
Query OK, 1 row affected (0.01 sec)

mysql> select * from t14;
+---+-------+
| a | b     |
+---+-------+
| 1 | good  |
| 2 | yes   |
| 3 | hello |
+---+-------+
3 rows in set (0.00 sec)

可以看到我们并没有插入数据a,而a默认从1开始自增。

而如果指明插入a:

mysql> insert into t14 (a, b) values (100, 'hello');
Query OK, 1 row affected (0.01 sec)

mysql> insert into t14 (b) values ('hello');
Query OK, 1 row affected (0.01 sec)

mysql> select * from t14;
+-----+-------+
| a   | b     |
+-----+-------+
|   1 | good  |
|   2 | yes   |
|   3 | hello |
| 100 | hello |
| 101 | hello |
+-----+-------+
5 rows in set (0.00 sec)

如果手动设置了a(比历史值大),那么就从手动设置的位置开始自增。

7.3 创建表时设置自增长起始值

创建表,并将自增长值初始值设置为100

mysql> create table t15(
    -> a int primary key auto_increment,
    -> b varchar(10)
    -> )auto_increment=100;
Query OK, 0 rows affected (0.03 sec)

连续插入数据:

mysql> insert into t15 (b) values ('good');
Query OK, 1 row affected (0.01 sec)

mysql> insert into t15 (b) values ('mysql');
Query OK, 1 row affected (0.01 sec)

mysql> select * from t15;
+-----+-------+
| a   | b     |
+-----+-------+
| 100 | good  |
| 101 | mysql |
+-----+-------+
2 rows in set (0.00 sec)

7.4 获取最后一次自增长的值

mysql> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
|              101 |
+------------------+
1 row in set (0.00 sec)

八、唯一键约束

一张表中有往往有很多字段需要唯一性,数据不能重复,但是一张表中只能有一个主键:唯一键就可以解决表中有多个字段需要唯一性约束的问题。一张表中主键只能有一个,但是唯一键可以有多个。

唯一键的本质和主键差不多,唯一键允许为空,而且可以有多个null,空字段不做唯一性比较。

mysql> create table stu( 
    -> id char(20) unique comment '这是一个学生的唯一键',
    -> name varchar(32) not null
    -> );
Query OK, 0 rows affected (0.03 sec)

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

插入相同id的数据:

mysql> insert into stu (id, name) values ('111', '张三');
Query OK, 1 row affected (0.01 sec)

mysql> insert into stu (id, name) values ('111', '李四');
ERROR 1062 (23000): Duplicate entry '111' for key 'id'

可以看到不能插入相同的id值。

mysql> insert into stu (id, name) values (NULL, '李四');
Query OK, 1 row affected (0.00 sec)

mysql> insert into stu (id, name) values (NULL, '李四');
Query OK, 1 row affected (0.02 sec)

mysql> insert into stu (id, name) values (NULL, '李四');
Query OK, 1 row affected (0.01 sec)

mysql> select * from stu;
+------+--------+
| id   | name   |
+------+--------+
| 111  | 张三   |
| NULL | 李四   |
| NULL | 李四   |
| NULL | 李四   |
+------+--------+
4 rows in set (0.00 sec)

唯一键和主键一样,不能重复。但是可以有多个NULL。

8.1 唯一键和主键的区别

主键和唯一键并不冲突而且是相互补充的。

举个例子:

我们把学号作为主键,但是每一行的信息还包括电话号码,不同的学号对应的电话号码不肯能一样,此时我们就可以在电话号码列添加唯一键。

主键和唯一键侧重点不同:
主键主要是保证表中一行的唯一性,而唯一键则是保证当前列的数据不会冲突。

mysql> create table student(
    -> id char(20) primary key,
    -> name varchar(20) not null,
    -> tel char(20) unique key
    -> );
Query OK, 0 rows affected (0.06 sec)

插入数据:

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

mysql> insert into student values ('112', '李四', '12345');
ERROR 1062 (23000): Duplicate entry '12345' for key 'tel'

8.2 唯一键加上非空约束

唯一键加上非空约束后,就和主键的作用一样了。但是记住,他们俩的侧重点不同,主键修饰非业务字段,而唯一键修饰业务字段,均保证字段的唯一性。

九、外键约束

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

  • 举个例子:
mysql> create table student(
    -> id int unsigned primary key auto_increment,
    -> name varchar(20) not null,
    -> tel varchar(20) not null,
    -> class_id int
    -> );
Query OK, 0 rows affected (0.03 sec)

mysql> create table class(
    -> id int primary key,
    -> name varchar(32) not null
    -> );
Query OK, 0 rows affected (0.02 sec)

插入数据:

#插入班级数据
mysql> insert into class values (1, '一班');
Query OK, 1 row affected (0.01 sec)

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

#插入学生数据
mysql> insert into student (name, tel, class_id) values ('张三', '123456', 1);
Query OK, 1 row affected (0.00 sec)

mysql> insert into student (name, tel, class_id) values ('李四', '133425', 2);
Query OK, 1 row affected (0.01 sec)

mysql> insert into student (name, tel, class_id) values ('王五', '155499', 2);
Query OK, 1 row affected (0.02 sec)

查看:

mysql> select * from student;
+----+--------+--------+----------+
| id | name   | tel    | class_id |
+----+--------+--------+----------+
|  1 | 张三   | 123456 |        1 |
|  2 | 李四   | 133425 |        2 |
|  4 | 王五   | 155499 |        2 |
+----+--------+--------+----------+
3 rows in set (0.00 sec)

mysql> select * from class;
+----+--------+
| id | name   |
+----+--------+
|  1 | 一班   |
|  2 | 二班   |
+----+--------+
2 rows in set (0.00 sec)

这里的学生表就是教室表的从表,教室是主表。
学生表里的class_id就对应了教室表中的id字段。

可以看到这里的教室一共就两个,但是程序员插入学生信息的时候可能会填成3班
还有一种情况就是删除了其中的一个班级,学生表中的班级就不存在了。
所以mysql就需要外键约束

9.1 建立外键约束

现在我们想要插入学生的时候如果班级不存在就不允许插入。

foreign key (从表字段名) references 主表()
mysql> create table student(
    -> id int unsigned primary key,
    -> name varchar(20) not null,
    -> tel varchar(20) unique key,
    -> class_id int,
    -> foreign key(class_id) references class (id)
    -> );

【MySQL】表的约束_第7张图片

9.2 向从表里插入数据

mysql> insert into student values(1, '张三', '110', 1);
Query OK, 1 row affected (0.01 sec)

mysql> insert into student values(2, '李四', '120', 2);
Query OK, 1 row affected (0.00 sec)

mysql> insert into student values(3, '王五', '130', 3);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test_db`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`))

建立外键的本质其实就是把相关性交给MySQL去审核了,提前告诉MySQL表之间的约束关系,那么当用户插入不符合业务逻辑的数据的时候,MySQL不允许你插入。

mysql> select * from student;
+----+--------+------+----------+
| id | name   | tel  | class_id |
+----+--------+------+----------+
|  1 | 张三   | 110  |        1 |
|  2 | 李四   | 120  |        2 |
+----+--------+------+----------+
2 rows in set (0.00 sec)

9.3 主表删除数据

mysql> delete from class where id=1;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`test_db`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`))

因为主表的主键列被其他的从表关联着,所以无法删除。

只有把从表的相关联的数据删除掉后才能删除主表的数据。

你可能感兴趣的:(MySQL,mysql,数据库)