【MySQL】_3.MySQL表的约束

目录

1. 数据库约束

2. 约束类型

3. NULL约束

4. UNIQUE:唯一约束

5. DEFAULT:默认值约束

6. PRIMARY KEY:主键约束

7. FOREIGH KEY:外键约束


1. 数据库约束

数据库约束就是数据库针对里面的数据能写什么,给出的一组“检验规则”;

这样的约束,可以程序员人工保证,也可以是程序自动保证,程序的存储能力与纪律性远远超过人脑。约束就是为了提高效率与准确性,让数据库该软件集成的一个针对数据校验的功能;

2. 约束类型

(1)NOT NULL:表示某列不能存储NULL值,即必填项;

(2)UNIQUE:保证某列的每行必须有唯一的值;

(3)DEFAULT:规定没有给列赋值的默认值;

(4)PRIMARY KEY(主键):NOT NULL和UNIQUE的结合:

确保某列(或多列组合)有唯一标识,有助于更容易更快速地找到表中的一个特定记录;

(5)FOREING KEY(外键):保证一个表中的数据匹配另一个表中的值的参照完整性;

(6)CHECK:保证列中的值符合指定的条件。(mysql5不支持,此处不赘述)

3. NULL约束

以student表为例,普通创建方式为:

mysql> create table student(id int, name varchar(20));
Query OK, 0 rows affected (0.04 sec)

不带NULL约束的建表方式可以插入NULL值:

mysql> insert into student values(null,null);
Query OK, 1 row affected (0.05 sec)

mysql> select* from student;
+------+------+
| id   | name |
+------+------+
| NULL | NULL |
+------+------+
1 row in set (0.00 sec)

带NULL约束的建表方式为:

mysql> create table student (id int not null, name varchar(20) not null);
Query OK, 0 rows affected (0.12 sec)

查看该表结构为:

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

可见此时表结构的NULL一栏标志为NO,此时试插入NULL值会报错:

mysql> insert into student values(null,null);
ERROR 1048 (23000): Column 'id' cannot be null

4. UNIQUE:唯一约束

在插入或修改数据时,会先进行查询该数据是否已经存在,不存在则插入,存在则插入失败;

以student表为例,普通创建方式为:

mysql> create table student(id int, name varchar(20));
Query OK, 0 rows affected (0.04 sec)

不带UNIQUE约束的建表方式可以插入重复值:

mysql> insert into student values(1,"张三");
Query OK, 1 row affected (0.06 sec)

mysql> insert into student values(1,"李四");
Query OK, 1 row affected (0.02 sec)

mysql> insert into student values(2,"张三");
Query OK, 1 row affected (0.03 sec)

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

带唯一约束的建表方式为:

mysql> create table student(id int unique,name varchar(20));
Query OK, 0 rows affected (0.09 sec)

查看表结构:

mysql> desc student;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | YES  | UNI | NULL    |       |
| name  | varchar(20) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.01 sec)

可见此时表结构的Key一栏标志为UNI,此时插入重复的id值会报错:

mysql> insert into student values(1,"张三");
Query OK, 1 row affected (0.07 sec)

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

注:带有unique约束的插入数据方式相比普通插入多了遍历表与查找数据的成本,故而效率相较较低; 

5. DEFAULT:默认值约束

普通创建的类的表结构为:

mysql> desc student;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | YES  | UNI | NULL    |       |
| name  | varchar(20) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+

不完全指定列插入信息后:

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

mysql> select*from student;
+------+------+
| id   | name |
+------+------+
|    1 | 张三 |
|    2 | NULL |
+------+------+
2 rows in set (0.00 sec)

可见id为2的同学的姓名一栏为NULL。

带有默认约束的建表方式为:

mysql> create table student(id int,name varchar(20) default "xxx");
Query OK, 0 rows affected (0.09 sec)

令name默认值为xxx,不完全指定列插入信息后:

mysql> insert into student values(1,"张三");
Query OK, 1 row affected (0.07 sec)

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

mysql> select* from student;
+------+------+
| id   | name |
+------+------+
|    1 | 张三 |
|    2 | xxx  |
+------+------+
2 rows in set (0.00 sec)

注:默认值是insert指定列插入时,其他未被指定到的列就按照默认值进行填充;

6. PRIMARY KEY:主键约束

主键是一条记录在表中的身份标识:

带有主键约束的建表方式为:

mysql> create table student(id int primary key,name varchar(20));
Query OK, 0 rows affected (0.07 sec)

此时将id作为主键,查看表结构为:

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

可见此时Key一栏将id标注为PRI,主键约束=NULL约束 +唯一约束,该数据不可为空,不能重复。试插入以下数据:

mysql> insert into student values(null,"张三");
ERROR 1048 (23000): Column 'id' cannot be null
mysql> insert into student values(1,"张三");
Query OK, 1 row affected (0.10 sec)

mysql> insert into student values(1,"张三");
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'

注:(1)其实创建主键时可以使用一列作为主键,也可以使用多列作为复合主键,但是这种情况非常少见;

(2)有很多方法可以保证不重复的为记录安排主键,MySQL提供了“自增主键” auto_increment 的方法,令MySQL自行增加:

查看表结构:

mysql> create table student(id int primary key auto_increment, name varchar(20));
Query OK, 0 rows affected (0.14 sec)

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

Extra列id一栏有auto_increment标识,此时再插入数据时,可以手动指定值,也可以让MySQL自己分配,如果要令MySQL自行分配,自insert语句时将id设为null即可;

mysql> insert into student values(null,"张三");
Query OK, 1 row affected (0.03 sec)

mysql> insert into student values(null,"李四");
Query OK, 1 row affected (0.11 sec)

mysql> insert into student values(null,"王五");
Query OK, 1 row affected (0.04 sec)

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

注:(1) 自增主键只基于上一条进行自增,与前面的主键无关:

mysql> select* from student;
+-----+------+
| id  | name |
+-----+------+
|   1 | 张三 |
|   2 | 李四 |
|   3 | 王五 |
| 100 | 赵六 |
+-----+------+
4 rows in set (0.00 sec)

mysql> insert into student values(null,"田七");
Query OK, 1 row affected (0.02 sec)

mysql> select* from student;
+-----+------+
| id  | name |
+-----+------+
|   1 | 张三 |
|   2 | 李四 |
|   3 | 王五 |
| 100 | 赵六 |
| 101 | 田七 |
+-----+------+
5 rows in set (0.00 sec)

(2)如果数据库为单机部署,则自增主键可供使用;

但如果数据库为分布式部署,自增主键就不适用了; 

7. FOREIGH KEY:外键约束

外键是指两张表之间相互关联:

mysql> create table class(classId int primary key auto_increment, className varchar(20));
Query OK, 0 rows affected (0.10 sec)

mysql> create table student(studentId int primary key auto_increment,
    -> name varchar(20),
    -> classId int,
    -> foreign key(classId) references class(classId));
Query OK, 0 rows affected (0.14 sec)

此时就要求student表中每个记录的classId需在class表中的classId一列中存在,在初始状态下class表为空,在student表中插入任何数据都会报错:

mysql> select* from class;
Empty set (0.00 sec)

mysql> insert into student values(1,"张三",1);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`testdemo1`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`classId`) REFERENCES `class` (`classid`))

(1)外键新增:

mysql> insert into class values(null,"java001");
Query OK, 1 row affected (0.10 sec)

mysql> insert into class values(null,"java002");
Query OK, 1 row affected (0.06 sec)

mysql> insert into class values(null,"java003");
Query OK, 1 row affected (0.02 sec)

mysql> select* from class;
+---------+-----------+
| classId | className |
+---------+-----------+
|       1 | java001   |
|       2 | java002   |
|       3 | java003   |
+---------+-----------+
3 rows in set (0.00 sec)

mysql> insert into student values(null,"张三",1);
Query OK, 1 row affected (0.06 sec)

mysql> select* from student;
+-----------+------+---------+
| studentId | name | classId |
+-----------+------+---------+
|         1 | 张三 |       1 |
+-----------+------+---------+
1 row in set (0.00 sec)

(2)外键修改:

直接修改会报错:

mysql> update student set classId=10 where studentId=1;
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`testdemo1`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`classId`) REFERENCES `class` (`classid`))

注:(1)student表受到class表的约束,此时就称class表为student表的父表,student表为class表的子表;

(2)先填充class表,再新增或修改student表记录时,MySQL会根据该记录去父表中查询是否存在,如果存在才能进行后续操作,不存在则操作失败;

(3)父表在约束子表的同时,子表也在反向约束父表,父表不能删除或修改已被子表使用或依赖的数据,也会触发报错:

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

(4)如果要修改子类外键关联数据,不能结束外键约束,可以在子表新增一列标记数据是否有效,当不再使用该数据时,可以将该数据设置为无效,为逻辑删除。

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