vlambda博客
学习文章列表

约束自己还是约束别人?不!俺说的是MySQL中的约束呢!

约束是什么鬼?来自百科的解释:

约束是一个汉语词语,读音是yuē shù,意思是指有缠缚,束缚,限制,管束,处罚等意思。古有盟约之意,如《战国策·燕策》:“坚明约束。”中约束一词。

额。。。好像跑题了,回到正题。

MySQL中的约束概述

约束是一种限制,它通过限制表中的数据,来确保数据的完整性和唯一性。

例如,在某数据表中有一个存储金额的字段,如果随便输入字符串类型的数据,那这些无效的值就毫无意义了。


MySQL支持以下约束:

1. 主键约束

2. 外键约束

外键约束经常和主键约束一起使用,用来确保数据的一致性。例如,有一个汽车店,只有宝马、奔驰、本田、丰田4个品牌,那么,你来到这个汽车店买车,就只能选择这4个品牌,不能购买其它的品牌。

3. 唯一约束

唯一约束与主键约束有一个相似的地方,就是它们都能够确保列的唯一性。与主键约束不同的是,唯一约束在一个表中可以有多个,并且设置唯一约束的列是允许有空值的,虽然只能有一个空值。

例如,在主机信息表中,要避免表中的主机名重名,就可以把主机名列设置为唯一约束。

4. 检查约束

检查约束是用来检查数据表中,字段值是否有效的一个手段。

5. 非空约束

非空约束用来约束表中的字段不能为空。例如,在主机表中,如果不添加主机名,那么这条记录是没有用的。

6. 默认值约束

默认值约束用来约束当数据表中某个字段不输入值时,自动为其添加一个已经设置好的值。

例如,将主机录入CMDB信息时,如果不输入主机名叫啥,那么会默认设置一个主机名(比如host001)或者输入一个“localhost”。

默认值约束通常用在已经设置了非空约束的列,这样能够防止数据表在录入数据时出现错误。

以上 6 种约束中,一个数据表中只能有一个主键约束,其它约束可以有多个。

主键约束

1. 设置单字段主键

# 创建表,将hostid设置为主键
create table hosts (
hostid BIGINT UNSIGNED PRIMARY KEY,
name VARCHAR(64),
status INT DEFAULT 0
);
# 查看表结构
mysql> desc hosts;
+--------+-----------------+------+-----+---------+-------+
| Field  | Type            | Null | Key | Default | Extra |
+--------+-----------------+------+-----+---------+-------+
| hostid | bigint unsigned | NO   | PRI | NULL    |       |
| name   | varchar(64)     | YES  |     | NULL    |       |
| status | int             | YES  |     | 0       |       |
+--------+-----------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql>
 

定义主键的另外一种方式,如下:

# 创建表,将hostid设置为主键
create table hosts_new (
hostid BIGINT UNSIGNED,
name VARCHAR(64),
status INT DEFAULT 0,
PRIMARY KEY(hostid) # 此处定义主键
);

#
 查看
mysql> desc hosts_new;
+--------+-----------------+------+-----+---------+-------+
| Field  | Type            | Null | Key | Default | Extra |
+--------+-----------------+------+-----+---------+-------+
| hostid | bigint unsigned | NO   | PRI | NULL    |       |
| name   | varchar(64)     | YES  |     | NULL    |       |
| status | int             | YES  |     | 0       |       |
+--------+-----------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql>
 

2. 在创建表时设置联合主键

所谓的联合主键,就是这个主键是由一张表中多个字段组成的。

比如,设置学生选课数据表时,使用学生编号做主键还是用课程编号做主键呢?如果用学生编号做主键,那么一个学生就只能选择一门课程。如果用课程编号做主键,那么一门课程只能有一个学生来选。显然,这两种情况都是不符合实际情况的。

实际上设计学生选课表,要限定的是一个学生只能选择同一课程一次。因此,学生编号和课程编号可以放在一起共同作为主键,这也就是联合主键了。

注意:当主键是由多个字段组成时,不能直接在字段名后面声明主键约束。

创建数据表 hosts,假设表中没有主键 id,为了唯一确定一台主机,可以把 name、hostid联合起来作为主键

mysql> create table hosts(
    -> hostid BIGINT UNSIGNED,
    -> name VARCHAR(64),
    -> status INT DEFAULT 0,
    -> PRIMARY KEY(hostid,name)
    -> );
Query OK, 0 rows affected (0.02 sec)

mysql>
 desc hosts;
+--------+-----------------+------+-----+---------+-------+
| Field  | Type            | Null | Key | Default | Extra |
+--------+-----------------+------+-----+---------+-------+
| hostid | bigint unsigned | NO   | PRI | NULL    |       |
| name   | varchar(64)     | NO   | PRI | NULL    |       |
| status | int             | YES  |     | 0       |       |
+--------+-----------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql>
 

3. 在修改表时添加主键约束

主键约束不仅可以在创建表的同时创建,也可以在修改表时添加。但是需要注意的是,设置成主键约束的字段中不允许有空值。

语法:

ALTER TABLE <数据表名> ADD PRIMARY KEY(<字段名>);

修改hosts表,将hostid设置为主键

# 先查看一个表,此表没有主键
mysql> desc hosts;
+--------+-----------------+------+-----+---------+-------+
| Field  | Type            | Null | Key | Default | Extra |
+--------+-----------------+------+-----+---------+-------+
| hostid | bigint unsigned | YES  |     | NULL    |       |
| name   | varchar(64)     | YES  |     | NULL    |       |
| status | int             | YES  |     | 0       |       |
+--------+-----------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

#
 修改表,添加主键
mysql> alter table hosts add PRIMARY KEY(hostid); 
Query OK, 0 rows affected (0.16 sec)
Records: 0  Duplicates: 0  Warnings: 0

#
 再次查看
mysql> desc hosts;
+--------+-----------------+------+-----+---------+-------+
| Field  | Type            | Null | Key | Default | Extra |
+--------+-----------------+------+-----+---------+-------+
| hostid | bigint unsigned | NO   | PRI | NULL    |       |
| name   | varchar(64)     | YES  |     | NULL    |       |
| status | int             | YES  |     | 0       |       |
+--------+-----------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql>
 

4. 删除主键约束

当一个表中不需要主键约束时,就需要从表中将其删除。删除主键约束的方法要比创建主键约束容易的多。

mysql> alter table hosts drop PRIMARY KEY;
Query OK, 0 rows affected (0.08 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql>
 desc hosts;
+--------+-----------------+------+-----+---------+-------+
| Field  | Type            | Null | Key | Default | Extra |
+--------+-----------------+------+-----+---------+-------+
| hostid | bigint unsigned | NO   |     | NULL    |       |
| name   | varchar(64)     | YES  |     | NULL    |       |
| status | int             | YES  |     | 0       |       |
+--------+-----------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql>
 

由于主键约束在一个表中只能有一个,因此不需要指定主键名就可以删除一个表中的主键约束。

5. 主键自增长

在MySQL中,当主键定义为自增长后,这个主键的值就不再需要用户输入数据了,而由数据库系统根据定义自动赋值。每增加一条记录,主键会自动以相同的步长进行增长。

通过给字段添加 AUTO_INCREMENT 属性来实现主键自增长

案例

mysql> create table hosts (
    -> hostid BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    -> name VARCHAR(64),
    -> status INT DEFAULT 0
    -> );
Query OK, 0 rows affected (0.03 sec)

mysql>
 desc hosts;
+--------+-----------------+------+-----+---------+----------------+
| Field  | Type            | Null | Key | Default | Extra          |
+--------+-----------------+------+-----+---------+----------------+
| hostid | bigint unsigned | NO   | PRI | NULL    | auto_increment |
| name   | varchar(64)     | YES  |     | NULL    |                |
| status | int             | YES  |     | 0       |                |
+--------+-----------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)

mysql>
 insert into hosts(name,status) values('pc01',0);
Query OK, 1 row affected (0.00 sec)

mysql>
 insert into hosts(name,status) values('pc02',0); 
Query OK, 1 row affected (0.01 sec)

mysql>
 insert into hosts(name,status) values('pc03',1);
Query OK, 1 row affected (0.00 sec)

mysql>
 insert into hosts(name,status) values('pc10',1);  
Query OK, 1 row affected (0.00 sec)

mysql>
 insert into hosts(name,status) values('pc12',0);
Query OK, 1 row affected (0.00 sec)

mysql>
 select * from hosts;
+--------+------+--------+
| hostid | name | status |
+--------+------+--------+
|      1 | pc01 |      0 |
|      2 | pc02 |      0 |
|      3 | pc03 |      1 |
|      4 | pc10 |      1 |
|      5 | pc12 |      0 |
+--------+------+--------+
5 rows in set (0.00 sec)

mysql>
 

外键约束

1. 在创建表时设置外键约束

案例:创建interface表,并在表 interface 上创建外键约束,约束名称为c_interface_1,让它的键 hostid 作为外键关联到表hosts的主键hostid

# 创建hosts表
mysql> create table hosts (
    -> hostid int(4) PRIMARY KEY AUTO_INCREMENT,
    -> name VARCHAR(64),
    -> status INT DEFAULT 0
    -> );
Query OK, 0 rows affected, 1 warning (0.04 sec)


#
 创建interface表,并在表 interface 上创建外键约束,约束名称为c_interface_1,让它的键 hostid 作为外键关联到表 hosts 的主键hostid
mysql> create table interface (
    -> interfaceid BIGINT UNSIGNED,
    -> ip VARCHAR(64) DEFAULT '127.0.0.1',
    -> hostid int(4),
    -> CONSTRAINT c_interface_1 FOREIGN KEY(hostid) REFERENCES hosts(hostid)
    -> );
Query OK, 0 rows affected, 1 warning (0.03 sec)

#
 查看interface表的创建语句
mysql> show create table interface\G;
*************************** 1. row ***************************
       Table: interface
Create Table: CREATE TABLE `interface` (
  `interfaceid` bigint unsigned DEFAULT NULL,
  `ip` varchar(64) DEFAULT '127.0.0.1',
  `hostid` int DEFAULT NULL,
  KEY `c_interface_1` (`hostid`),
  CONSTRAINT `c_interface_1` FOREIGN KEY (`hostid`) REFERENCES `hosts` (`hostid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

ERROR: 
No query specified
mysql> 
mysql> 

2. 删除外键约束

ALTER TABLE interface DROP FOREIGN KEY c_interface_1;

3. 在修改表时添加外键约束

ALTER TABLE interface ADD CONSTRAINT c_interface_1 FOREIGN KEY(hostid) REFERENCES hosts(hostid);

唯一约束

MySQL唯一约束(Unique Key)是指所有记录中字段的值不能重复出现。例如,为id字段加上唯一性约束后,每条记录的id值都是唯一的,不能出现重复的情况。如果主机信息表中的hostid字段,其中一条记录的hostid值为‘76549’,那么该表中就不能出现另一条记录的hostid值也为‘76549’。

唯一约束与主键约束相似的是它们都可以确保列的唯一性。不同的是,唯一约束在一个表中可有多个,并且设置唯一约束的列允许有空值,但是只能有一个空值。而主键约束在一个表中只能有一个,且不允许有空值。比如,在主机信息表中,为了避免表中主机名重名,可以把主机名设置为唯一约束。

  • 唯一约束的关键字:UNIQUE

1. 在创建表时设置唯一约束

语法

<字段名> <数据类型> UNIQUE

案例:创建users表,userid字段设置主键约束,name字段设置唯一约束

create table users(
userid int(4) PRIMARY KEY,
name varchar(20) unique,
alias varchar(20)
);

2. 在修改表时添加唯一约束

语法:

ALTER TABLE <数据表名> ADD CONSTRAINT <唯一约束名> UNIQUE(<列名>);

案例:将现有的users表中的alias字段设置唯一约束

alter table users add constraint c_1 unique(alias);

3. 删除唯一约束

语法

ALTER TABLE <表名> DROP INDEX <唯一约束名>;

案例:删除名为c_1的唯一约束

# 先查看创建叫的语句,就可以知道约束名叫啥
mysql> show create table users\G;
*************************** 1. row ***************************
       Table: users
Create Table: CREATE TABLE `users` (
  `userid` int NOT NULL,
  `name` varchar(20) DEFAULT NULL,
  `alias` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`userid`),
  UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

ERROR: 
No query specified

mysql>
 

#
 删除名为c_1的唯一约束
alter table users drop index c_1;

检查约束

MySQL检查约束(CHECK)是用来检查数据表中字段值有效性的一种手段,可以通过 CREATE TABLE 或 ALTER TABLE 语句实现。设置检查约束时要根据实际情况进行设置,这样能够减少无效数据的输入。

1. 在创建表时设置检查约束

语法

CHECK(<检查约束>)

案例,创建users表,age字段设置检查约束,约束条件是:值大于0和小于100

# 创建users表,age字段设置检查约束
create table users(
userid int(4) primary key,
name varchar(20) unique,
age int,
check(age>0 and age<100)
);

#
 查看创建表语句
mysql> show create table users\G;
*************************** 1. row ***************************
       Table: users
Create Table: CREATE TABLE `users` (
  `userid` int NOT NULL,
  `name` varchar(20) DEFAULT NULL,
  `age` int DEFAULT NULL,
  PRIMARY KEY (`userid`),
  UNIQUE KEY `name` (`name`),
  CONSTRAINT `users_chk_1` CHECK (((`age` > 0) and (`age` < 100)))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

2. 在修改表时添加检查约束

语法

ALTER TABLE tb_emp7 ADD CONSTRAINT <检查约束名> CHECK(<检查约束>)

3. 删除检查约束

语法

ALTER TABLE <数据表名> DROP CONSTRAINT <检查约束名>;

非空约束

MySQL 非空约束(NOT NULL)指字段的值不能为空。对于使用了非空约束的字段,如果用户在添加数据时没有指定值,数据库系统就会报错。可以通过 CREATE TABLE 或 ALTER TABLE 语句实现。在表中某个列的定义后加上关键字 NOT NULL 作为限定词,来约束该列的取值不能为空。

1. 在创建表时设置非空约束

创建表时可以使用 NOT NULL 关键字设置非空约束,具体的语法格式如下:

<字段名> <数据类型> NOT NULL;

2. 在修改表时添加非空约束

如果在创建表时忘记了为字段设置非空约束,也可以通过修改表进行非空约束的添加。

修改表时设置非空约束的语法格式如下:

ALTER TABLE <数据表名> CHANGE COLUMN <字段名> <字段名> <数据类型> NOT NULL;

3. 删除非空约束

修改表时删除非空约束的语法规则如下:

ALTER TABLE <数据表名> CHANGE COLUMN <字段名> <字段名> <数据类型> NULL;

默认值约束

默认值(Default)的完整称呼是“默认值约束(Default Constraint)”,用来指定某列的默认值。在表中插入一条新记录时,如果没有为某个字段赋值,系统就会自动为这个字段插入默认值。

例如,主机信息表中,主机位于A机房的比较多,那么机房位置就可以默认为“A”,系统就会自动为这个字段赋值为“A”。

1. 在创建表时设置默认值约束

语法

<字段名> <数据类型> DEFAULT <默认值>;

2. 在修改表时添加默认值约束

修改表时添加默认值约束的语法格式如下:

ALTER TABLE <数据表名> CHANGE COLUMN <字段名> <数据类型> DEFAULT <默认值>;

3. 删除默认值约束

当一个表中的列不需要设置默认值时,就需要从表中将其删除。

修改表时删除默认值约束的语法格式如下:

ALTER TABLE <数据表名> CHANGE COLUMN <字段名> <字段名> <数据类型> DEFAULT NULL;

好了,关于mysql的约束,今晚就此搁笔,时间有限。笔者认为,除了要学好数据库的约束之外,还要学会自我约束,比如约束自己准时睡觉,这不,我要准备睡了,不能熬夜哦!