(基础篇)SQL 约束

什么是 SQL 的约束?

  约束(constraint)是一种限制,它通过对表的行或列的数据做出限制,来确保表的数据的完整性、唯一性。

  约束分为列级约束(对一个数据列创建的约束)和表级约束(对多个数据列创建的约束)。

  一般我们在创建数据表的时候都会加入一些约束,如主键约束,非空约束,默认约束。

种类

  约束按作用范围可以分为:

约束类型 列级约束 表级约束
关键字 NOT NULL 、DEFAULT UNIQUE 、PRIMARY KEY 、FOREIGN KEY

  当然,上述还可以具体细分为:

约束类型 默认约束 非空约束 主键约束 唯一约束 外键约束
关键字 DEFAULT NOT NULL PRIMARY KEY UNIQUE FOREIGN KEY

默认约束

  默认值约束(DEFAULT)规定,当有DEFAULT约束的列,插入数据为空时,将使用默认值。

  默认值常用于一些可有可无的字段,比如用户的个性签名,若用户没有设置,系统给他应该设定一个默认的文本,比如空文本或 ‘这个人太懒了,没有留下任何信息’。

1
2
3
4
5
6
7
8
9
CREATE TABLE user(
username varchar(20) NOT NULL PRIMARY KEY,
password varchar(20) NOT NULL,
usersignature varchar(50) DEFAULT '这个人太懒了,没有留下任何信息'
);
# 正常插入数据
INSERT INTO user(username,password,usersignature) VALUES ('jack','123','天地不仁。。。');
# 插入新数据,usersignature 为空,所以使用默认值
INSERT INTO user(username,password) VALUES ('lucy','123');

  输入以下命令

1
SELECT * FROM user;

  表中usersignature 字段将被 DEFAULT 的默认值 这个人太懒了,没有留下任何信息 填充:
默认约束

非空约束

  非空约束(NOT NULL),言简意赅,被非空约束的列,在插入值时必须非空。

1
2
username varchar(20) NOT NULL,
password varchar(20) NOT NULL,

主键约束

  主键(PRIMARY KEY)是用于约束表中的一行,作为这一行的唯一标识符,主键不能有重复记录且不能为空,主键可以设置为一个列或多个列。

  • 每张数据表只能有一个主键
  • 主键保持记录的唯一性
  • 主键自动为NOT NULL

  在数据库中,若有两行记录的数据完全一样,那么如何区分呢?
  答案是无法区分,若有两行记录完全相同, MySQL 就会认定它们是同一个实体,这与现实生活是存在差别的。

  假如我们要存储一个学生的信息,信息包含姓名,班级,学号,性别,年龄等等。

  可学校人这么多,重名的人不知凡几,比如王伟,刘伟。。。因此我们在挑选主键时可以选择学号(大学学号不会重复)来区分不同的学生。

1
2
3
4
5
6
CREATE TABLE student(
snumber int NOT NULL PRIMARY KEY,
sname varchar(20) NOT NULL,
sclass varchar(20) NOT NULL,
sex int(2) NOT NULL
);

唯一约束

  唯一约束(UNIQUE)规定一张表中指定的一列的值必须不能有重复值,即这一列每个值都是唯一的,和主键约束不同的是它的值可以为NULL
  举个例子,不同学生的日记写的肯定不一样,要么没做为NULL,要么做了,但每个人的日记内容肯定不同。这个时候就可以用唯一约束定义日记这份作业了。

1
2
3
4
5
6
7
8
9
10
11
CREATE TABLE student(
sid int NOT NULL AUTO_INCREMENT PRIMARY KEY,
sname VARCHAR(20) NOT NULL,
sex VARCHAR(20) NOT NULL,
homework varchar(50) UNIQUE
)
# 插入数据
INSERT INTO student VALUES (1, '小明', '男', NULL);
INSERT INTO student VALUES (2, '小红', '女', NULL);
INSERT INTO student VALUES (3, '小王', '男', '庐山旅游日记');
INSERT INTO student VALUES (4, '小张', '男', '长城游记');

唯一约束

外键约束(不建议使用)

  外键为某个表中的一列,它包含另一个表的主键值,定义了两个表之间的关系。
  外键(FOREIGN KEY)既能确保数据的一致性、完整性,也能表现表与表之间的关系(一对一、一对多)。
  一个表可以有多个外键,每个外键必须 REFERENCES(参考)另一个表的主键,被外键约束的列,取值必须在它参照的列中有对应值。

使用要求

  • 数据表的存储引擎必须为 InnoDB ;
  • 父表和子表必须使用相同的存储引擎,而且禁止使用临时表;
  • 外键列和参照列必须具有相似的数据类型。其中数字的长度或是否有符号为必须相同,而字符的长度可以不同;
  • 外键列和参照列必须创建索引。若外键列不存在索引,MySQL 则自动创建索引。

  假如现在你是电脑店老板,数据库中有商品表和供货商表,商品表设计时会添加一个指向供货商 id 的外键(该 id 为供货商表的主键),表示这个商品所属的供货商,外键将确保这个外键指向的记录是存在的。
  若你尝试删除一个供货商,而该供货商还有商品存在于商品表中,那么操作将无法完成并报错。
  为什么会报错呢?
  因为你删除了该供货商之后,该供货商的商品还在商品表中,你下次还想进这个商品,找谁?
  同理,你在创建一个商品的时候也不能为他指定一个不存在的供货商 id。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 创建供货商表
CREATE TABLE vendors(
vend_id int NOT NULL PRIMARY KEY,
vend_name VARCHAR(20) NOT NULL,
vend_phone int NOT NULL,
vend_address VARCHAR(50) NOT NULL
);
# 创建商品表
CREATE TABLE products(
product_id int NOT NULL PRIMARY KEY,
product_name VARCHAR(20) NOT NULL,
product_price int NOT NULL,
product_category VARCHAR(20) NOT NULL,
vend_id int NOT NULL,
FOREIGN KEY(vend_id) REFERENCES vendor(vend_id)
);

# 先插入供货商信息
INSERT INTO vendors VALUES (1, '苹果', 6666666, '美国');
INSERT INTO vendors VALUES (2, '三星', 5555555, '韩国');
INSERT INTO vendors VALUES (3, '华为', 888888888, '中国');

# 才能再插入商品信息
INSERT INTO products VALUES (1, 'iphoneX', 6666, '手机', 1);
INSERT INTO products VALUES (2, 'samsung 10', 8888, '手机', 2);
INSERT INTO products VALUES (3, 'HUAWEI p30', 111111, '手机', 3);
INSERT INTO products VALUES (4, 'mac pro 19', 22222, '电脑', 1);

供货商信息
商品信息

为什么要用外键?

  好处如下:

  • 供应商信息不重复,从而不浪费时间和空间;
  • 若供应商信息变动,可以只更新vendors表中的单个记录,相关表中的数据不用改动;
  • 由于数据无重复,显然数据是一致的,这使得处理数据更简单。
  • products表只存储产品信息,它除了存储供应商 ID(vendors表的主键)外不存储其他供应商信息。vendors表的主键又叫作products的外键, 它将vendors表与products表关联,利用供应商 ID 能从vendors表中找出 相应供应商的详细信息。

注意

  约束可以在一个列写完后定义,也可以写完所有列后再定义,如对主键约束而言:

1
2
3
4
5
6
7
8
9
10
11
12
CREATE TABLE student(
sid int AUTO_INCREMENT PRIMARY KEY
sname VARCHAR(20) NOT NULL,
sex VARCHAR(20) NOT NULL
)
# 或者
CREATE TABLE student(
sid int AUTO_INCREMENT,
sname VARCHAR(20) NOT NULL,
sex VARCHAR(20) NOT NULL,
PRIMARY KEY(sid)
)

  那么,具体在建表时应该如何使用呢?

  一般混合使用两者,即非空等约束直接在列后定义,而索引型约束在所有列定义完成后再集中定义,便于查询。

参考

  • Ben Forta. MySQL 必知必会 [M]. 人民邮电出版社, 2009

文章信息

时间 说明
2019-02-09 初稿
2022-08-20 微调
0%