目录
1. 数据库约束
2. 约束类型
3. NULL约束
4. UNIQUE:唯一约束
5. DEFAULT:默认值约束
6. PRIMARY KEY:主键约束
7. FOREIGH KEY:外键约束
数据库约束就是数据库针对里面的数据能写什么,给出的一组“检验规则”;
这样的约束,可以程序员人工保证,也可以是程序自动保证,程序的存储能力与纪律性远远超过人脑。约束就是为了提高效率与准确性,让数据库该软件集成的一个针对数据校验的功能;
(1)NOT NULL:表示某列不能存储NULL值,即必填项;
(2)UNIQUE:保证某列的每行必须有唯一的值;
(3)DEFAULT:规定没有给列赋值的默认值;
(4)PRIMARY KEY(主键):NOT NULL和UNIQUE的结合:
确保某列(或多列组合)有唯一标识,有助于更容易更快速地找到表中的一个特定记录;
(5)FOREING KEY(外键):保证一个表中的数据匹配另一个表中的值的参照完整性;
(6)CHECK:保证列中的值符合指定的条件。(mysql5不支持,此处不赘述)
以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
在插入或修改数据时,会先进行查询该数据是否已经存在,不存在则插入,存在则插入失败;
以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约束的插入数据方式相比普通插入多了遍历表与查找数据的成本,故而效率相较较低;
普通创建的类的表结构为:
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指定列插入时,其他未被指定到的列就按照默认值进行填充;
主键是一条记录在表中的身份标识:
带有主键约束的建表方式为:
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)如果数据库为单机部署,则自增主键可供使用;
但如果数据库为分布式部署,自增主键就不适用了;
外键是指两张表之间相互关联:
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)如果要修改子类外键关联数据,不能结束外键约束,可以在子表新增一列标记数据是否有效,当不再使用该数据时,可以将该数据设置为无效,为逻辑删除。