说明:文章所有内容均截选自用户“实验楼包工头”发布在实验楼上的教程【MySQL 基础课程】,想要详细的学习SQL,点击教程即可免费学习了;未经允许,禁止转载;
约束是一种限制,它通过对表的行或列的数据做出限制,来确保表的数据的完整性、唯一性。文章将在实践操作中熟悉 MySQL 中的几种约束。
1 约束分类
听名字就知道,约束是一种限制,它通过对表的行或列的数据做出限制,来确保表的数据的完整性、唯一性。
在MySQL中,通常有这几种约束:
约束类型: | 主键 | 默认值 | 唯一 | 外键 | 非空 |
---|---|---|---|---|---|
关键字: | PRIMARY KEY | DEFAULT | UNIQUE | FOREIGN KEY | NOT NULL |
2 建立含约束的表
为了方便介绍这几种约束,我们先建立一个数据库。
当然不用你一行一行地输入命令搭建这个数据库,实验楼已经为你准备好了。首先打开 Xfce 终端,输入命令进入 /home/shiyanlou/Desktop
目录:
cd Desktop
使用 git 命令将需要的数据文件下载到本地文件夹:
git clone https://github.com/shiyanlou/SQL3
下载完成后,输入命令开启 MySQL 服务并使用 root 用户登录:
#打开 MySQL 服务
sudo service mysql start
#使用 root 用户登录
mysql -u root
刚才下载的 SQL3 目录下,有个文件 MySQL-03-01.sql
,其中包含的代码可以新建一个数据库 mysql_shiyan
,然后在其中创建三张表 department
,employee
,project
,它们包含了各种约束。
(SQL3 目录在桌面上,你可以用Gedit查看里面的 MySQL-03-01.sql
文件。)
加载文件中的数据,需要在 MySQL 控制台中输入命令:
source /home/shiyanlou/Desktop/SQL3/MySQL-03-01.sql;
查看一下这个数据库,输入命令 show tables;
,可见:
3 主键
主键 (PRIMARY KEY)是用于约束表中的一行,作为这一行的唯一标识符,在一张表中通过主键就能准确定位到一行,因此主键十分重要。主键不能有重复且不能为空。
在 MySQL-03-01.sql
中,这里有主键:
也可以这样定义主键:

还有一种特殊的主键——复合主键。主键不仅可以是表中的一列,也可以由表中的两列或多列来共同标识,比如:

4 默认值约束
默认值约束 (DEFAULT) 规定,当有 DEFAULT 约束的列,插入数据为空时,将使用默认值。
在 MySQL-03-01.sql
中,这段代码包含了 DEFAULT 约束:

DEFAULT 约束只会在使用 INSERT 语句(上一实验介绍过)时体现出来,INSERT语句中,如果被 DEFAULT 约束的位置没有值,那么这个位置将会被 DEFAULT 的值填充,如语句:
# 正常插入数据
INSERT INTO department(dpt_name,people_num) VALUES('dpt1',11);
#插入新的数据,people_num 为空,使用默认值
INSERT INTO department(dpt_name) VALUES('dpt2');
输入命令 SELECT * FROM department;
,可见表中第二行的people_num 被 DEFAULT 的值 (10) 填充:

5 唯一约束
唯一约束 (UNIQUE) 比较简单,它规定一张表中指定的一列的值必须不能有重复值,即这一列每个值都是唯一的。
在 MySQL-03-01.sql
中,也有 UNIQUE 约束:

当 INSERT 语句新插入的数据和已有数据重复的时候,如果有 UNIQUE约束,则 INSERT 失败,比如:
INSERT INTO employee VALUES(01,'Tom',25,3000,110110,'dpt1');
INSERT INTO employee VALUES(02,'Jack',30,3500,110110,'dpt2');
结果如图:
6 外键约束
外键 (FOREIGN KEY) 既能确保数据完整性,也能表现表之间的关系。
一个表可以有多个外键,每个外键必须 REFERENCES (参考) 另一个表的主键,被外键约束的列,取值必须在它参考的列中有对应值。

在 INSERT 时,如果被外键约束的值没有在参考列中有对应,比如以下命令,参考列 (department 表的 dpt_name) 中没有dpt3,则INSERT 失败:
INSERT INTO employee VALUES(02,'Jack',30,3500,114114,'dpt3');
可见之后将 dpt3 改为 dpt2(department 表中有 dpt2),则插入成功:
7 非空约束
非空约束 (NOT NULL),听名字就能理解,被非空约束的列,在插入值时必须非空。

在MySQL中违反非空约束,不会报错,只会有警告,比如以下语句:
#INSERT 成功 age 为空,因为没有非空约束,表中显示 NULL
INSERT INTO employee(id,name,salary,phone,in_dpt) VALUES(03,'Jim',3400,119119,'dpt2');
#警告 salary 被非空约束,值为空,表中显示0
INSERT INTO employee(id,name,age,phone,in_dpt) VALUES(04,'Bob',23,123456,'dpt1');
结果如图,出现警告,但还是插入数据成功,实验楼的环境是 5.5.50
,5.6
版本以上的 MySQL 会报错,禁止插入不符合非空约束的数据:

此时 employee 表的内容为:

总结
文章通过一个数据库实例了解了主键、默认值、外键、非空、唯一这几种约束的特性,这几种约束都是最常见的,需要仔细理解每种约束的含义及使用场景。
教程【MySQL 基础课程】共17个实验+3个挑战,课程列表如下:



网友评论
➜ 桌面 git clone https://github.com/shiyanlou/SQL3
正克隆到 'SQL3'...
remote: Counting objects: 12, done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 12 (delta 3), reused 12 (delta 3), pack-reused 0
展开对象中: 100% (12/12), 完成.
➜ 桌面 ls
bleachbit-root (复件).desktop qtcreator.desktop
bluefish.desktop Shell 快速指南 - 静默虚空 - 博客园.pdf
cheese.desktop simplescreenrecorder.desktop
display-im6.q16.desktop SQL3
gimp.desktop steam.desktop
gnome-search-tool.desktop ubuntu-kylin-software-center.desktop
gnome-system-monitor.desktop ubuntu安装和查看已安装 - foward.molly.pdf
libreoffice-draw.desktop uget-gtk.desktop
libreoffice-startcenter.desktop 给你的linux电脑跑个分(unixbench) - 简书.pdf
mate-power-preferences.desktop 解决Ubuntu死机.pdf
mysql用户权限.pdf 图标发送到桌面.pdf
nemiver.desktop 新文件
pencil.desktop
➜ 桌面 sudo service mysql start
[sudo] dflx的密码:
➜ 桌面 mysql -u root
ERROR 1698 (28000): Access denied for user 'root'@'localhost'
➜ 桌面 sudo mysql -u root
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.7.20-0ubuntu0.17.04.1 (Ubuntu)
Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> source /home/dflx/gmysql>
mysql> source /home/dflx/SQL3/MySQL-03-01.sql
Query OK, 1 row affected (0.00 sec)
Database changed
Query OK, 0 rows affected (0.03 sec)
Query OK, 0 rows affected (0.05 sec)
Query OK, 0 rows affected (0.02 sec)
Query OK, 1 row affected (0.01 sec)
mysql> insert department(dp_name) values('dpt2');
ERROR 1054 (42S22): Unknown column 'dp_name' in 'field list'
mysql> insert department(dpt_name) values('dpt2');
Query OK, 1 row affected (0.01 sec)
mysql> select * from department;
+----------+------------+
| dpt_name | people_num |
+----------+------------+
| dp1 | 11 |
| dpt2 | 10 |
+----------+------------+
2 rows in set (0.00 sec)
+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
| employee | CREATE TABLE `employee` (
`id` int(10) NOT NULL,
`name` char(20) DEFAULT NULL,
`age` int(10) DEFAULT NULL,
`salary` int(10) NOT NULL,
`phone` int(12) NOT NULL,
`in_dpt` char(20) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `phone` (`phone`),
KEY `emp_fk` (`in_dpt`),
CONSTRAINT `emp_fk` FOREIGN KEY (`in_dpt`) REFERENCES `department` (`dpt_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
1 row in set (0.00 sec)
+------------------------+
| Tables_in_mysql_shiyan |
+------------------------+
| department |
| employee |
| project |
+------------------------+
3 rows in set (0.00 sec)
mysql> desc emplopee;
ERROR 1146 (42S02): Table 'mysql_shiyan.emplopee' doesn't exist
mysql> desc employee;
+--------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+----------+------+-----+---------+-------+
| id | int(10) | NO | PRI | NULL | |
| name | char(20) | YES | | NULL | |
| age | int(10) | YES | | NULL | |
| salary | int(10) | NO | | NULL | |
| phone | int(12) | NO | UNI | NULL | |
| in_dpt | char(20) | NO | MUL | NULL | |
+--------+----------+------+-----+---------+-------+
6 rows in set (0.01 sec)