13.2.5 数据库约束
前面创建的数据表仅仅指定了一些列定义,这仅仅是数据表的基本功能。除此之外,所有的关系数据库都支持对数据表使用约束,通过约束可以更好地保证数据表里数据的完整性。约束是在表上强制执行的数据校验规则,约束主要用于保证数据库里数据的完整性。除此之外,当表中数据存在相互依赖性时,可以保护相关的数据不被删除。
5种完整性约束
大部分数据库支持下面5种完整性约束。
not null
:非空约束,指定某列不能为空。
unique
:唯一约束,指定某列或者几列组合不能重复。
primary key
:主键,指定该列的值可以唯一地标识该条记录。
foreign key
:外键,指定该行记录从属于主表中的一条记录,主要用于保证参照完整性。
check
:检查,指定一个布尔表达式,用于指定对应列的值必须满足该表达式。
MySQL不支持check约束
虽然大部分数据库都支持上面5种约束,但**MySQL
不支持CHECK
约束**,虽然MySQL
的SQL
语句也可以使用CHECK
约束,但这个CHECK
约束不会有任何作用。
约束分类
虽然约束的作用只是用于保证数据表里数据的完整性,但约束也是数据库对象,并被存储在系统表中,也拥有自己的名字。根据约束对数据列的限制,约束分为如下两类。
- 单列约束:每个约束只约束一列。
- 多列约束:每个约束可以约束多个数据列。
什么时候指定约束
为数据表指定约束有如下两个时机。
- 建表的同时为相应的数据列指定约束。
- 建表后创建,以修改表的方式来增加约束。
大部分约束都可以采用列级约束语法或者表级约束语法。下面依次介绍5种约束的建立和删除(约束通常无法修改)。
提示:
MySQL
使用information_schema
数据库里的TABLE_CONSTRAINTS
表来保存该数据库实例中所有的约束信息,用户可以通过查询TABLE_CONSTRAINTS
表来获取该数据库的约束信息。
1.NOT NULL约束
非空约束用于确保指定列不允许为空,非空约束是比较特殊的约束,它只能作为列级约束使用,只能使用列级约束语法定义。这里要介绍一下SQL
中的null
值,SQL
中的null
不区分大小写。SQL
中的null
具有如下特征。
- 所有数据类型的值都可以是
null
,包括int
、float
、boolean
等数据类型。
- 与
Java
类似的是,空字符串不等于null
,0也不等于null
。
建表的时候指定NOT NULL约束
如果需要在建表时为指定列指定非空约束,只要在列定义后增加not null
即可。建表语句如下:
1 2 3 4 5
| CREATE TABLE `hehe` ( `hehe_id` int(11) NOT NULL, `hehe_name` varchar(255) NOT NULL, `hehe_gender` varchar(2) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
not null约束的默认值
**在插入数据的时候,如果某列没有赋值,MySQL
会赋给一个默认值.**
对于not null
约束的列,
- 如果类型为
int
,则默认值为0
- 如果默认值为
varchar
,则默认值为空字符串.
实例
现在插入一条数据insert into hehe(hehe_gender) values('小王');
,这里只给第三个属性赋值,第一和第二没有赋值,此时表中的数据如下所示:
1 2 3 4 5 6 7 8 9 10
| mysql> insert into hehe(hehe_gender) values('小王'); Query OK, 1 row affected
mysql> select * from hehe; +---------+-----------+-------------+ | hehe_id | hehe_name | hehe_gender | +---------+-----------+-------------+ | 0 | | 小王 | +---------+-----------+-------------+ 1 row in set
|
可以看到第一列填入了默认值0
,而第二列好像什么都没有填入,但其实第二列填入的是空字符串
而不是NULL
(not null
约束的列当然不能填入null).
现在再来插入一条数据:insert into hehe(hehe_id) values(1);
这里只填入第一列,第二列和第三列让MySQL默认填写.
查询结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| mysql> select * from hehe; +---------+-----------+-------------+ | hehe_id | hehe_name | hehe_gender | +---------+-----------+-------------+ | 0 | | 小王 | +---------+-----------+-------------+ 1 row in set mysql> insert into hehe(hehe_id) values(1); Query OK, 1 row affected
mysql> select * from hehe; +---------+-----------+-------------+ | hehe_id | hehe_name | hehe_gender | +---------+-----------+-------------+ | 0 | | 小王 | | 1 | | NULL | +---------+-----------+-------------+ 2 rows in set
|
因为第三列的hehe_gender
默认值为NULL
,所以MySQL
给该列填上了默认值NULL
,
而第二列的hehe_name
使用了not null
约束,不能填写NULL
,此时MySQL
填写上一个空字符串
.
alter table修改表时增加和删除非空约束
除此之外,也可以在使用alter table
修改表时增加或者删除非空约束,SQL
命令如下:
增加非空约束
1 2
| alter table hehe modify hehe_gender varchar(2) not null
|
效果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| mysql> desc hehe; +-------------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------------+--------------+------+-----+---------+-------+ | hehe_id | int(11) | NO | | NULL | | | hehe_name | varchar(255) | NO | | NULL | | | hehe_gender | varchar(2) | YES | | NULL | | +-------------+--------------+------+-----+---------+-------+ 3 rows in set
mysql> alter table hehe modify hehe_gender varchar(2) not null; Query OK, 3 rows affected Records: 3 Duplicates: 0 Warnings: 2
mysql> desc hehe; +-------------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------------+--------------+------+-----+---------+-------+ | hehe_id | int(11) | NO | | NULL | | | hehe_name | varchar(255) | NO | | NULL | | | hehe_gender | varchar(2) | NO | | NULL | | +-------------+--------------+------+-----+---------+-------+
|
默认值
此时再次查询表中数据,可以发现第二行第三列的值已经变成列空字符串
了,不再是原来的NULL,如下所示:
1 2 3 4 5 6 7 8
| mysql> select * from hehe; +---------+-----------+-------------+ | hehe_id | hehe_name | hehe_gender | +---------+-----------+-------------+ | 0 | | 小王 | | 1 | | | +---------+-----------+-------------+ 2 rows in set
|
取消非空约束并指定默认值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| mysql> desc hehe; +-------------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------------+--------------+------+-----+---------+-------+ | hehe_id | int(11) | NO | | NULL | | | hehe_name | varchar(255) | NO | | NULL | | | hehe_gender | varchar(2) | NO | | NULL | | +-------------+--------------+------+-----+---------+-------+ 3 rows in set
mysql> alter table hehe modify hehe_name varchar(255) default 'xyz' null; Query OK, 3 rows affected Records: 3 Duplicates: 0 Warnings: 0
mysql> desc hehe; +-------------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------------+--------------+------+-----+---------+-------+ | hehe_id | int(11) | NO | | NULL | | | hehe_name | varchar(255) | YES | | xyz | | | hehe_gender | varchar(2) | NO | | NULL | | +-------------+--------------+------+-----+---------+-------+ 3 rows in set
|
默认值
这时候我们再次查询:
1 2 3 4 5 6 7 8
| mysql> select * from hehe; +---------+-----------+-------------+ | hehe_id | hehe_name | hehe_gender | +---------+-----------+-------------+ | 0 | | 小王 | | 1 | | | +---------+-----------+-------------+ 2 rows in set
|
这里可以发现第二列原来的默认值(空字符串),并没有直接变成xyz
.这是因为default语句定义的字符串默认值,在新插入的记录才有效(其实原来的空字符串也是字符串,MySQL该列已经有数据了不需要自己填写默认值,所以不会使用xyz
覆盖原来的空字符串)
现在再插入一条记录insert into hehe (hehe_id) values(2);
此时第二列没有赋值,将填入默认值xyz
.如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| mysql> select * from hehe; +---------+-----------+-------------+ | hehe_id | hehe_name | hehe_gender | +---------+-----------+-------------+ | 0 | | 小王 | | 1 | | | +---------+-----------+-------------+ 2 rows in set
mysql> insert into hehe (hehe_id) values(2); Query OK, 1 row affected
mysql> select * from hehe; +---------+-----------+-------------+ | hehe_id | hehe_name | hehe_gender | +---------+-----------+-------------+ | 0 | | 小王 | | 1 | | | | 2 | xyz | | +---------+-----------+-------------+ 3 rows in set mysql>
|