MySQL基础知识—约束(重点)

介绍

约束:constraint

在创建表的时候,可以给表中的字段加上约束来保证表中数据的完整性,有效性。

常见约束

非空约束not null

非空约束not null约束的字段不能为NULL。

只有列级约束。

示例

mysql> create table t_vip(id int,name varchar(255) not null);
Query OK, 0 rows affected (0.25 sec)

mysql> desc t_vip;
+-------+--------------+------+-----+---------+-------+
| Field | Type         | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id    | int          | YES  |     | NULL    |       |
| name  | varchar(255) | NO   |     | NULL    |       |
+-------+--------------+------+-----+---------+-------+
2 rows in set (0.04 sec)
mysql> insert into t_vip(id,name) values(1,'kd');
Query OK, 1 row affected (0.04 sec)

mysql> insert into t_vip(id,name) values(2,'hl');
Query OK, 1 row affected (0.04 sec)

mysql> insert into t_vip(id) values(2);
1364 - Field 'name' doesn't have a default value

可以看到name没有默认值,表示不能为空。

唯一性约束unique

唯一性约束unique约束的字段不能重复,但是可以为NULL。

示例1 列级约束

mysql>  create table t_vip(id int,name varchar(255) unique,email varchar(255));
Query OK, 0 rows affected (0.65 sec)

mysql> insert into t_vip(id,name,email) values(1,'kd','[email protected]');
Query OK, 1 row affected (0.08 sec)

mysql> select * from t_vip;
+----+------+------------+
| id | name | email      |
+----+------+------------+
|  1 | kd   | [email protected] |
+----+------+------------+
1 row in set (0.03 sec)

mysql> insert into t_vip(id,name,email) values(2,'kd','[email protected]');
1062 - Duplicate entry 'kd' for key 't_vip.name'

mysql> insert into t_vip(id) values(2);
Query OK, 1 row affected (0.07 sec)

mysql> select * from t_vip;
+----+------+------------+
| id | name | email      |
+----+------+------------+
|  1 | kd   | [email protected] |
|  2 | NULL | NULL       |
+----+------+------------+
2 rows in set (0.03 sec)

可以看出,name字段被unique约束,不能重复,一旦重复后会出现如下报错:

1062 - Duplicate entry 'kd' for key 't_vip.name'

但是,name字段可以为NULL,而NULL可以重复。

示例2 表级约束

需求:name和email两个字段联合起来具有唯一性

mysql>  create table t_vip(
			id int,
			name varchar(255),
			email varchar(255),
			unique(name,email));
Query OK, 0 rows affected (0.32 sec)

mysql> desc t_vip;
+-------+--------------+------+-----+---------+-------+
| Field | Type         | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id    | int          | YES  |     | NULL    |       |
| name  | varchar(255) | YES  | MUL | NULL    |       |
| email | varchar(255) | YES  |     | NULL    |       |
+-------+--------------+------+-----+---------+-------+
3 rows in set (0.03 sec)

mysql> insert into t_vip(id,name,email) values
(1,'kd','[email protected]');
Query OK, 1 row affected (0.05 sec)

mysql> insert into t_vip(id,name,email) values
(2,'kd','[email protected]');
Query OK, 1 row affected (0.04 sec)

mysql> insert into t_vip(id,name,email) values
(3,'kd1','[email protected]');
Query OK, 1 row affected (0.03 sec)

mysql> insert into t_vip(id,name,email) values(4,'kd','[email protected]');
1062 - Duplicate entry '[email protected]' for key 't_vip.name'

从上面的示例中,可以看出两个字段联合的唯一性约束中,两个字段可以分别不同,只有两个字段完全一样的时候才会报错。

主键约束(primary key,简称pk)

主键字段:添加了主键约束的字段。

主键值:主键字段中的每一个值,每一行记录的唯一标识。

任何一张表都应该有主键。

主键值一般都是定长的,使用int,bigint,char等,不建议使用varchar。

特征

主键值不能为NULL,也不能重复(not null + unique)。

列级约束写法—单一主键

mysql> drop table if exists t_vip;
Query OK, 0 rows affected (0.23 sec)

mysql> create table t_vip(
    	id int primary key,
   		new varchar(255));
Query OK, 0 rows affected (0.25 sec)

mysql> insert into t_vip(id, new) values(1,'kd');
Query OK, 1 row affected (0.08 sec)

mysql> insert into t_vip(id, new) values(2,'kd1');
Query OK, 1 row affected (0.06 sec)

mysql> insert into t_vip(id, new) values(2,'kd2');
1062 - Duplicate entry '2' for key 't_vip.PRIMARY'
mysql> insert into t_vip(new) values('kd2');
1364 - Field 'id' doesn't have a default value
mysql> select * from t_vip;
+----+-----+
| id | new |
+----+-----+
|  1 | kd  |
|  2 | kd1 |
+----+-----+
2 rows in set (0.02 sec)

从上面的代码中可以看出,主键值不能为空,也不能重复,不然会报错。

表级约束写法

主要给多个字段联合起来添加约束(复合主键:两个及以上的字段做主键)—使用较少。

mysql> create table t_vip(
    	id int,
    	new varchar(255),
    	primary key(id));
Query OK, 0 rows affected (0.45 sec)

mysql>  insert into t_vip(id, new) values(1,'kd');
Query OK, 1 row affected (0.05 sec)

mysql> insert into t_vip(id, new) values(1,'kd2');
1062 - Duplicate entry '1' for key 't_vip.PRIMARY'

自然主键

主键值是一个自然数,在实际开发中用的多,只要不重复就行,不需要有意义。

业务主键

主键值和业务紧密关联,例如用银行卡账号做主键。

当业务发生变动时,可能影响主键值。

自动维护主键方法

create table t_vip(
	id int primary key auto_increment,
	name varchar(255)
);

在创建表的时候,使用auto_increment(自增,类型为int,bigint)即可。

外键约束(foreign key,简称fk)

术语

外键字段:添加了外键约束的字段。

外键值:外键字段中的每一个值。

MySQL 外键约束(FOREIGN KEY)是表的一个特殊字段,经常与主键约束一起使用。对于两个具有关联关系的表而言,相关联字段中主键所在的表就是主表(父表),外键所在的表就是从表(子表)。

外键用来建立主表与从表的关联关系,为两个表的数据建立连接,约束两个表中数据的一致性和完整性。比如,一个水果摊,只有苹果、桃子、李子、西瓜等 4 种水果,那么,你来到水果摊要买水果就只能选择苹果、桃子、李子和西瓜,其它的水果都是不能购买的。

主表删除某条记录时,从表中与之对应的记录也必须有相应的改变。一个表可以有一个或多个外键,外键可以为空值,若不为空值,则每一个外键的值必须等于主表中主键的某个值。

定义外键时,需要遵守下列规则:

  • 主表必须已经存在于数据库中,或者是当前正在创建的表。如果是后一种情况,则主表与从表是同一个表,这样的表称为自参照表,这种结构称为自参照完整性。
  • 必须为主表定义主键。
  • 主键不能包含空值,但允许在外键中出现空值。也就是说,只要外键的每个非空值出现在指定的主键中,这个外键的内容就是正确的。
  • 在主表的表名后面指定列名或列名的组合。这个列或列的组合必须是主表的主键或候选键。
  • 外键中列的数目必须和主表的主键中列的数目相同。
  • 外键中列的数据类型必须和主表主键中对应列的数据类型相同。
  • 删除表:先删除子表,后删除父表
  • 创建表:先创建父表,后创建子表
  • 删除数据:先删除子表中的数据,再删除父表中的数据
  • 插入数据:先插入父表中,再插入子表中

示例

业务背景:

设计数据库表,来描述“班级和学生”的信息。

第一种方案:班级和学生存储在一张表中

t_student
no(pk)         name         classno         classname
1              jack         101             一班
2              lili         101             一班
3              lilei        102             二班
4              zhangsan     102             二班

上面的方案会造成数据冗余,空间浪费。

第二种方案:一张班级表,一张学生表

t_class 班级表
classno(pk)     classname
101             一班
102             二班


t_student 学生表
no(pk)          name              cno(班级编号,FK——引用t_class表的classno)
1               jack              101
2               lili              101
3               lilei             102
4               zhangsan          102

对于上面学生表中的班级编号字段,需要有约束来让班级编号和班级表中的主键classno联系起来,让班级编号只能取classno中的值(101和102)。

这里cno有外键约束,cno字段为具有外键约束的字段。

代码:

创建t_class和t_student表

mysql> create table t_class(classno int primary key,classname varchar(255));
Query OK, 0 rows affected (0.27 sec)

mysql> create table t_student(
    no int primary key auto_increment,
    name varchar(255),
    cno int,
    foreign key(cno) references t_class(classno)//外键约束
);
Query OK, 0 rows affected (0.42 sec)

mysql> desc t_student;
+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| no    | int          | NO   | PRI | NULL    | auto_increment |
| name  | varchar(255) | YES  |     | NULL    |                |
| cno   | int          | YES  | MUL | NULL    |                |
+-------+--------------+------+-----+---------+----------------+
3 rows in set (0.03 sec)

插入数据

mysql> insert into t_class(classno,classname) values(101,'一班');
Query OK, 1 row affected (0.05 sec)

mysql> insert into t_class(classno,classname) values(102,'二班');
Query OK, 1 row affected (0.07 sec)

mysql> select * from t_class;
+---------+-----------+
| classno | classname |
+---------+-----------+
|     101 | 一班      |
|     102 | 二班      |
+---------+-----------+
2 rows in set (0.04 sec)

mysql> insert into t_student(name,cno) values('jack',101);
Query OK, 1 row affected (0.08 sec)

mysql> insert into t_student(name,cno) values('lili',101);
Query OK, 1 row affected (0.04 sec)

mysql> insert into t_student(name,cno) values('lilei',102);
Query OK, 1 row affected (0.04 sec)

mysql> insert into t_student(name,cno) values('zhangsan',102);
Query OK, 1 row affected (0.04 sec)

mysql> select * from t_student;
+----+----------+-----+
| no | name     | cno |
+----+----------+-----+
|  1 | jack     | 101 |
|  2 | lili     | 101 |
|  3 | lilei    | 102 |
|  4 | zhangsan | 102 |
+----+----------+-----+
4 rows in set (0.03 sec)

然后查看t_student表中相关外键可以取到的值,如下图所示:

image-20211014211632078

 只有t_class主键classno中的两个值可以取。

检查约束

check(mysql没有,Oracle有)

not null和unique联合

mysql> create table t_vip(
    	id int,
    	name varchar(255) not null unique);
Query OK, 0 rows affected (0.26 sec)

mysql> desc t_vip;
+-------+--------------+------+-----+---------+-------+
| Field | Type         | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id    | int          | YES  |     | NULL    |       |
| name  | varchar(255) | NO   | PRI | NULL    |       |
+-------+--------------+------+-----+---------+-------+
2 rows in set (0.03 sec)

可以看出,name是not null 和unique联合约束后,name变成了主键primary key。(注意:Oracle中不一样!)

Guess you like

Origin blog.csdn.net/kuangd_1992/article/details/120693145