SQL约束用于规定表中的数据规则,如果存在违反约束的数据行为,行为会被约束终止。
约束可以在创建表时规定(通过CREATE TABLE语句),或者在表创建之后规定(通过ALTER TABLE语句)。
- 非空约束:
not null
- 唯一性约束:
unique
- 主键约束:
primary key
(PK) - 外键约束:
foreign key
(FK) - 检查约束:
check
- 默认值约束:
default
非空约束:not null
非空约束的字段不能为NULL。not null 只有列级约束,没有表级约束
- 列级约束:直接定义在特定列的定义后面,它仅适用于那一列。
- 表级约束:独立于单个列的定义,它们通常用于当约束条件涉及多个列时。
vip.sql
sql
drop table if exists t_vip;
create table t_vip(
id int,
name varchar(255) not null
);
唯一性约束: unique
唯一性约束unique约束的字段不能重复,但是可以为NULL。
sql
drop table if exists t_vip;
create table t_vip(
id int,
name varchar(255) unique, //name只能唯一
email varchar(255)
);
新需求:name和email两个字段联合起来具有唯一性!
sql
drop table if exists t_vip;
create table t_vip(
id int,
name varchar(255),
email varchar(255),
unique(name,email) // 约束没有添加在列的后面,这种约束被称为表级约束。
);
实例:unique 和not null可以联合
sql
drop table if exists t_vip;
create table t_vip(
id int,
name varchar(255) not null unique //联合使用
);
sql
mysql> desc t_vip;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(255) | NO | PRI | NULL | |
+-------+--------------+------+-----+---------+-------+
2 rows in set (0.01 sec)
在mysql当中,如果一个字段同时被not null和unique约束的话,该字段自动变成主键字段。
默认值约束:defalut
sql
drop table if exists t_student;
create table t_student(
no int,
name varchar(32),
sex char(1) default 'm', //default设置默认值 默认性别:'m'
age int(3),
email varchar(255)
);
查看表的数据类型
sql
mysql> desc t_student;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| no | int(11) | YES | | NULL | |
| name | varchar(32) | YES | | NULL | |
| sex | char(1) | YES | | m | |
| age | int(3) | YES | | NULL | |
| email | varchar(255) | YES | | NULL | |
+-------+--------------+------+-----+---------+-------+
5 rows in set (0.01 sec)
主键约束:primary key
记住:任何一张表都应该有主键,没有主键,表无效!
主键的特征:not null + unique(主键值不能是NULL,同时也不能重复!)
sql
drop table if exists t_vip;
create table t_vip(
id int primary key, //列级约束
name varchar(255)
);
例:使用表级约束,添加主键,同样实现功能
sql
create table t_vip(
id int,
name varchar(255),
primary key(id) //表级约束
);
表级约束主要是给多个字段联合起来添加约束
sql
drop table if exists t_vip;
create table t_vip(
id int,
name varchar(255),
email varchar(255),
primary key(id,name) // id和name联合起来做主键:复合主键!!!!
);
auto_increment
在mysql当中,有一种机制,可以帮助我们自动维护一个主键值
sql
create table t_vip(
id int primary key auto_increment, //auto_increment表示自增,从1开始,以1递增!
name varchar(255)
);
外键约束:foreign key
业务背景:请设计数据库表,来描述"班级和学生"的信息
第一种方案:班级和学生存储在一张表中
sql
t_student
no(pk) name classno classname
----------------------------------------------------------------------------------
1 jack 100 北京市大兴区亦庄镇第二中学高三1班
2 lucy 100 北京市大兴区亦庄镇第二中学高三1班
3 lilei 100 北京市大兴区亦庄镇第二中学高三1班
4 hanmeimei 100 北京市大兴区亦庄镇第二中学高三1班
5 zhangsan 101 北京市大兴区亦庄镇第二中学高三2班
6 lisi 101 北京市大兴区亦庄镇第二中学高三2班
7 wangwu 101 北京市大兴区亦庄镇第二中学高三2班
8 zhaoliu 101 北京市大兴区亦庄镇第二中学高三2班
以上方案缺点:数据冗余,空间浪费!这个设计是比较失败的!
第二种方案:班级一张表、学生一张表
sql
t_class 班级表
classno(pk) classname
------------------------------------------------------
100 北京市大兴区亦庄镇第二中学高三1班
101 北京市大兴区亦庄镇第二中学高三1班
sql
t_student 学生表
no(pk) name cno(FK引用t_class这张表的classno)
----------------------------------------------------------------
1 jack 100
2 lucy 100
3 lilei 100
4 hanmeimei 100
5 zhangsan 101
6 lisi 101
7 wangwu 101
8 zhaoliu 101
当cno字段没有任何约束的时候,可能会导致数据无效。可能出现一个102,但是102班级不存在。
所以为了保证cno字段中的值都是100和101,需要给cno字段添加外键约束。
那么:cno字段就是外键字段。cno字段中的每一个值都是外键值。
注意:
t_class是父表
t_student是子表
- 删除表的顺序:先删子,再删父。
- 创建表的顺序:先创建父,再创建子。
- 删除数据的顺序:先删子,再删父。
- 插入数据的顺序:先插入父,再插入子。
sql
drop table if exists t_student;
drop table if exists t_class;
create table t_class(
classno int primary key,
classname varchar(255)
);
create table t_student(
no int primary key auto_increment,
name varchar(255),
cno int,
foreign key(cno) references t_class(classno)
);
思考:子表中的外键引用的父表中的某个字段,被引用的这个字段必须是主键吗?
不一定是主键,但至少具有unique约束。
测试:外键可以为NULL吗?
外键值可以为NULL
sql
mysql> insert into t_student(name,cno) values('zhaoliu',NULL);
Query OK, 1 row affected (0.00 sec)
mysql> select * from t_student;
+----+-----------+------+
| no | name | cno |
+----+-----------+------+
| 1 | jack | 100 |
| 2 | lucy | 100 |
| 3 | lilei | 100 |
| 4 | hanmeimei | 100 |
| 5 | zhangsan | 101 |
| 6 | lisi | 101 |
| 7 | wangwu | 101 |
| 8 | zhaoliu | 101 |
| 10 | zhaoliu | NULL |
+----+-----------+------+
9 rows in set (0.00 sec)