我只想卷死各位,或者被各位卷死,在此特别感谢康师傅的MySQL教程


约束(constraint)概述

为什么需要约束

数据完整性(Data Integrity)是指数据的精确性(Accuracy)和可靠性(Reliability)。它是防止数据库中存在不符合语义规定的数据和防止因错误信息的输入输出造成无效操作或错误信息而提出的。

为了保证数据的完整性,SQL规范以约束的方式对表数据进行额外的条件限制。从以下四个方面考虑:

  • 实体完整性(Entity Integrity) :例如,同一个表中,不能存在两条完全相同无法区分的记录
  • 域完整性(Domain Integrity) :例如:年龄范围0-120,性别范围“男/女”
  • 引用完整性(Referential Integrity) :例如:员工所在部门,在部门表中要能找到这个部门
  • 用户自定义完整性(User-defined Integrity) :例如:用户名唯一、密码不能为空等,本部门经理的工资不得高于本部门职工的平均工资的5倍。

什么是约束

约束是表级的强制规定。

可以在创建表时规定约束(通过 CREATE TABLE 语句),或者在表创建之后通过 ALTER TABLE 语句规定约束。

约束的分类

  • 根据约束数据列的限制,约束可分为:
    • 单列约束:每个约束只约束一列
    • 多列约束:每个约束可约束多列数据
  • 根据约束的作用范围,约束可分为:
    • 列级约束:只能作用在一个列上,跟在列的定义后面
    • 表级约束:可以作用在多个列上,不与列一起,而是单独定义
位置 支持的约束类型 是否可以起约束名
列级约束: 列的后面 语法都支持,但外键没有效果 不可以
表级约束: 所有列的下面 默认和非空不支持,其他支持 可以(主键没有效果)
  • 根据约束起的作用,约束可分为:
    • NOT NULL 非空约束,规定某个字段不能为空
    • UNIQUE 唯一约束,规定某个字段在整个表中是唯一的
    • PRIMARY KEY 主键(非空且唯一)约束
    • FOREIGN KEY 外键约束
    • CHECK 检查约束
    • DEFAULT 默认值约束
  • 查看某个表已有的约束

1
2
3
4
-- information_schema数据库名(系统库)
-- table_constraints表名称(专门存储各个表的约束)
SELECT * FROM information_schema.table_constraints
WHERE table_name = '表名称';

非空约束

作用

限定某个字段/某列的值不允许为空

关键字

  • NOT NULL

特点

  • 默认,所有的类型的值都可以是NULL,包括INT、FLOAT等数据类型
  • 非空约束只能出现在表对象的列上,只能某个列单独限定非空,不能组合非空
  • 一个表可以有很多列都分别限定了非空
  • 空字符串’'不等于NULL,0也不等于NULL

添加非空约束

  • 建表时
1
2
3
4
5
CREATE TABLE 表名称(
字段名 数据类型,
字段名 数据类型 NOT NULL,
字段名 数据类型 NOT NULL
);
  • 举例
1
2
3
4
5
6
CREATE TABLE test1(
id INT NOT NULL,
last_name VARCHAR(25) NOT NULL,
email VARCHAR(50),
salary DECIMAL(10,2)
);
  • 测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
INSERT INTO test1
VALUES(1,'张三','zhangsan@gmail.com',8000);
-- 成功

INSERT INTO test1
VALUES(2,NULL,'test@outlook.com',5000);
-- 失败 报错:Column 'last_name' cannot be null

INSERT INTO test1(id,email)
VALUES(2,'butterfly@qq.com');
-- 失败 报错:Field 'last_name' doesn't have a default value
-- 没有给字段显式赋值时,字段为默认值,而这里没有设置默认值,默认值为NULL

UPDATE test1
SET last_name = NULL
WHERE id = 1;
-- 失败,Column 'last_name' cannot be null
  • 建表后,使用ALTER修改
1
2
3
4
5
6
7
ALTER TABLE test1
MODIFY email VARCHAR(50) NOT NULL;
-- 如果此时email字段下已经存在NULL值,则修改失败

INSERT INTO test1
VALUES(108,'王五',NULL,5000);
-- 错误:Column 'email' cannot be null

将 NOT NULL 改成 NULL 即可

1
2
3
4
5
6
ALTER TABLE test1
MODIFY email VARCHAR(50) NULL;

INSERT INTO test1
VALUES(73,'赵六',NULL,4399);
-- 成功

唯一性约束

作用

  • 用来限制某个字段/某列的值不能重复。

关键字

  • UNIQUE

特点

  • 同一个表可以有多个唯一约束。
  • 唯一约束可以是某一个列的值唯一,也可以多个列组合的值唯一。
  • 唯一性约束允许列值为空。
  • 在创建唯一约束的时候,如果不给唯一约束命名,就默认和列名相同。
  • MySQL会给唯一约束的列上默认创建一个唯一索引。

添加唯一约束

  • 建表时
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-- 列级约束
create table 表名称(
字段名 数据类型,
字段名 数据类型 unique,
字段名 数据类型 unique key,
字段名 数据类型
);

-- 表级约束
create table 表名称(
字段名 数据类型,
字段名 数据类型,
字段名 数据类型,
[constraint 约束名] unique key(字段名)
);
  • 举例
1
2
3
4
5
6
7
CREATE TABLE test2(
id INT UNIQUE, -- 列级约束
last_name VARCHAR(15),
email VARCHAR(25),
salary DECIMAL(10,2),
CONSTRAINT uk_test2_email UNIQUE(email) -- 表级约束
);
  • 添加数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
INSERT INTO test2
VALUES(1,'Tom','Tom@123.com',3500);

-- 错误:Duplicate entry '1' for key 'test2.id'
INSERT INTO test2
VALUES(1,'Jerry','Jerry@123.com',4000);

-- 错误:Duplicate entry 'Tom@123.com' for key 'test2.uk_test2_email'
INSERT INTO test2
VALUES(2,'Jerry','Tom@123.com',4500);

-- 可以向声明为UNIQUE的字段添加NULL值,且可以多次添加NULL值
INSERT INTO test2
VALUES(2,'Jerry',NULL,4500);

INSERT INTO test2
VALUES(3,'Coco',NULL,5000);
  • 建表后使用ALTER TABLE 添加约束
1
2
ALTER TABLE 表名称 
ADD [CONSTRAINT 约束名] UNIQUE KEY(字段列表); --KEY 可以省略
1
2
ALTER TABLE 表名称 
MODIFY 字段名 字段类型 UNIQUE;
  • 举例
1
2
3
4
5
ALTER TABLE test2
ADD CONSTRAINT uk_test2_sal UNIQUE(salary);

ALTER TABLE test2
MODIFY last_name VARCHAR(15) UNIQUE;

关于复合唯一约束

  • 格式
1
2
3
4
5
6
7
-- 字段列表中写的是多个字段名,多个字段名用逗号分隔
CREATE TABLE 表名称(
字段名 数据类型,
字段名 数据类型,
字段名 数据类型,
UNIQUE KEY(字段列表)
);
  • 举例
1
2
3
4
5
6
CREATE TABLE student(
sid INT, -- 学号
sname VARCHAR(20), -- 姓名
tel CHAR(11) UNIQUE KEY, -- 电话
cardid CHAR(18) UNIQUE KEY -- 身份证号
);
1
2
3
4
CREATE TABLE course(
cid INT, -- 课程编号
cname VARCHAR(20) -- 课程名称
);
1
2
3
4
5
6
7
CREATE TABLE student_course(
id INT,
sid INT,
cid INT,
score INT,
UNIQUE KEY(sid,cid) -- 复合唯一,每个学生的每门课只能有一次成绩
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
INSERT INTO student VALUES(1,'张三','13710011002','101223199012015623');-- 成功

INSERT INTO student VALUES(2,'李四','13710011003','101223199012015624');-- 成功

INSERT INTO course VALUES(1001,'Java'),(1002,'MySQL');-- 成功

INSERT INTO student_course VALUES
(1, 1, 1001, 89),
(2, 1, 1002, 90),
(3, 2, 1001, 88),
(4, 2, 1002, 56); -- 成功

INSERT INTO student_course VALUES
(5,1,1001,100); -- 错误:Duplicate entry '1-1001' for key 'student_course.sid'

删除唯一约束

  • 添加唯一性约束的列上也会自动创建唯一索引。

  • 删除唯一约束只能通过删除唯一索引的方式删除。

  • 删除时需要指定唯一索引名,唯一索引名就和唯一约束名一样。

  • 如果创建唯一约束时未指定名称,如果是单列,就默认和列名相同;如果是组合列,那么默认和()中排在第一个的列名相同。也可以自定义唯一性约束名。

  • 格式

1
2
3
4
5
6
7
8
-- 查看都有哪些约束
SELECT *
FROM information_schema.table_constraints
WHERE table_name = '表名';

-- 根据查到的约束名来删除约束
ALTER TABLE 表名称
DROP INDEX 索引名;
  • 举例
1
2
ALTER TABLE test2
DROP INDEX uk_test2_email;

PRIMARY KEY 约束

作用

用来唯一标识表中的一条记录

关键字

  • PRIMARY KEY

特点

  • 主键约束相当于唯一约束+非空约束的组合,主键约束列不允许重复,也不允许出现空值(举例:部门ID)
  • 一个表最多只能有一个主键约束,建立主键约束可以在列级别创建,也可以在表级别上创建。
  • 主键约束对应着表中的一列或者多列(复合主键)
  • 如果是多列组合的复合主键约束,那么这些列都不允许为空值,并且组合的值不允许重复。
  • MySQL的主键名总是PRIMARY,就算自己命名了主键约束名也没用。
  • 当创建主键约束时,系统默认会在所在的列或列组合上建立对应的主键索引(能够根据主键查询的,就根据主键查询,效率更高)。如果删除主键约束了,主键约束对应的索引就自动删除了。
  • 需要注意的一点是,不要修改主键字段的值。因为主键是数据记录的唯一标识,如果修改了主键的值,就有可能会破坏数据的完整性。

添加主键约束

  • 建表时添加主键约束
1
2
3
4
5
6
7
8
9
10
11
12
create table 表名称(
字段名 数据类型 primary key, -- 列级模式
字段名 数据类型,
字段名 数据类型
);

create table 表名称(
字段名 数据类型,
字段名 数据类型,
字段名 数据类型,
[constraint 约束名] primary key(字段名) -- 表级模式
);
  • 建表后增加主键约束
1
2
ALTER TABLE 表名称 
ADD PRIMARY KEY(字段列表);

关于复合主键

  • 格式
1
2
3
4
5
6
create table 表名称(
字段名 数据类型,
字段名 数据类型,
字段名 数据类型,
primary key(字段名1,字段名2) -- 表示字段1和字段2的组合是唯一的,也可以有更多个字段
);

删除主键约束

  • 格式
1
2
ALTER TABLE 表名称 
DROP PRIMARY KEY;

说明:删除主键约束,不需要指定主键名,因为一个表只有一个主键,删除主键约束后,非空约束还存在。

自增列 AUTO_INCREMENT

作用

某个字段的值自增

关键字

  • AUTO_INCREMENT

特点和要求

  • 一个表最多只能有一个自增长列
  • 当需要产生唯一标识或顺序符时,可设置自增长
  • 自增长列约束的列必须是键列(主键列,唯一键列)
1
2
3
4
5
-- 错误:Incorrect table definition; there can be only one auto column and it must be defined as a key
CREATE TABLE employee(
id INT AUTO_INCREMENT,
last_name VARCHAR(15)
);
  • 自增约束的列的数据类型必须是整数类型
1
2
3
4
5
-- 错误:Incorrect column specifier for column 'last_name'
CREATE TABLE employee(
id INT,
last_name VARCHAR(15) PRIMARY KEY AUTO_INCREMENT
);
  • 如果自增列指定了0和NULL,会在当前最大值的基础上自增
  • 如果自增列手动指定了具体值,直接赋值为具体值。

如何指定自增约束

  • 建表时
1
2
3
4
5
6
7
8
9
10
11
12
13
CREATE TABLE 表名称(
字段名 数据类型 PRIMARY KEY AUTO_INCREMENT,
字段名 数据类型 UNIQUE KEY NOT NULL,
字段名 数据类型 UNIQUE KEY,
字段名 数据类型 NOT NULL DEFAULT 默认值,
);

CREATE TABLE 表名称(
字段名 数据类型 DEFAULT 默认值 ,
字段名 数据类型 UNIQUE KEY AUTO_INCREMENT,
字段名 数据类型 NOT NULL DEFAULT 默认值,,
PRIMARY KEY(字段名)
);
  • 建表后
1
2
ALTER TABLE 表名称 
MODIFY 字段名 数据类型 AUTO_INCREMENT;

如何删除自增约束

1
2
3
4
5
ALTER TABLE 表名称 
MODIFY 字段名 数据类型 AUTO_INCREMENT;-- 给这个字段增加自增约束

ALTER TABLE 表名称
MODIFY 字段名 数据类型; -- 去掉AUTO_INCREMENT相当于删除

FOREIGN KEY 约束

作用

  • 限定某个表的某个字段的引用完整性。
  • 比如:员工表的员工所在部门的选择,必须在部门表能找到对应的部分。(不能把员工分配给不存在的部门)

关键字

  • FOREIGN KEY

主表和从表/父表和子表

  • 主表(父表):被引用的表,被参考的表
  • 从表(子表):引用别人的表,参考别人的表
  • 例如:员工表的员工所在部门这个字段的值要参考部门表:部门表是主表,员工表是从表。
  • 例如:学生表、课程表、选课表:选课表的学生和课程要分别参考学生表和课程表,学生表和课程表是主表,选课表是从表。

特点

  • 从表的外键列,必须引用/参考主表的主键或唯一约束的列,因为被依赖/被参考的值必须是唯一的
  • 在创建外键约束时,如果不给外键约束命名,默认名不是列名,而是自动产生一个外键名,但我们也可以指定外键约束名
  • 创建(CREATE)表时就指定外键约束的话,先创建主表,再创建从表(因为从表必须参考主表的主键或唯一约束列,详情见第一条)
  • 删表时,先删从表(或先删除外键约束),再删除主表(理由基本同上)
  • 当主表的记录被从表参照时,主表的记录将不允许删除,如果要删除数据,需要先删除从表中依赖该记录的数据,然后才可以删除主表的数据(但也不绝对,下面有提及到可以直接删除主表数据的情况)
  • 在从表中指定外键约束,并且一个表可以建立多个外键约束
  • 从表的外键列与主表被参照的列名字可以不相同,但是数据类型必须一样,逻辑意义一致。
  • 当创建外键约束时,系统默认会在所在的列上建立对应的普通索引。但是索引名是外键的约束名。(根据外键查询效率很高)
  • 删除外键约束后,必须手动删除对应的索引

添加外键约束

  • 建表时
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-- 先创建主表
CREATE TABLE 主表名称(
字段1 数据类型 PRIMARY KEY,
字段2 数据类型
);

-- 再创建从表
CREATE TABLE 从表名称(
字段1 数据类型 PRIMARY KEY,
字段2 数据类型,
-- 引用主表的主键或唯一约束列
[CONSTRAINT <外键约束名称>]
FOREIGN KEY(从表的某个字段)
REFERENCES 主表名(被参考字段)
);
  • 建表后

一般情况下,表与表的关联都是提前设计好了的,因此,会在创建表的时候就把外键约束定义好。不过,如果需要修改表的设计(比如添加新的字段,增加新的关联关系),但没有预先定义外键约束,那么,就要用修改表的方式来补充定义。

1
2
3
4
5
ALTER TABLE 从表名 
ADD [CONSTRAINT 约束名]
FOREIGN KEY (从表的字段)
REFERENCES 主表名(被引用字段)
[ON UPDATE xx][ON DELETE xx];

演示问题

被引用的字段不是主键,也没有唯一约束,故添加失败

1
2
3
4
5
6
7
8
9
10
11
CREATE TABLE dept(
did INT , #部门编号
dname VARCHAR(50) #部门名称
);

CREATE TABLE emp(
eid INT PRIMARY KEY, #员工编号
ename VARCHAR(5), #员工姓名
deptid INT, #员工所在的部门
FOREIGN KEY (deptid) REFERENCES dept(did)
);

从表的外键列与主表被参照的列名字可以不相同,但是数据类型必须一样,逻辑意义一致。

deptid为CHAR类型,did为INT类型,数据类型不一致

1
2
3
4
5
6
7
8
9
10
11
CREATE TABLE dept(
did INT PRIMARY KEY, #部门编号
dname VARCHAR(50) #部门名称
);

CREATE TABLE emp(
eid INT PRIMARY KEY, #员工编号
ename VARCHAR(5), #员工姓名
deptid CHAR, #员工所在的部门
FOREIGN KEY (deptid) REFERENCES dept(did)
);
  • 约束关系是针对双方的
  • 添加了外键约束后,主表的修改和删除数据受约束
  • 添加了外键约束后,从表的添加和修改数据受约束
  • 在从表上建立外键,要求主表必须存在
  • 删除主表时,要求从表从表先删除,或将从表中外键引用该主表的关系先删除

约束等级

  • Cascade方式 :在父表上update/delete记录时,同步update/delete掉子表的匹配记录
  • Set null方式 :在父表上update/delete记录时,将子表上匹配记录的列设为null,但是要注意子表的外键列不能为not null
  • No action方式 :如果子表中有匹配的记录,则不允许对父表对应候选键进行update/delete操作
  • Restrict方式 :同No action, 都是立即检查外键约束
  • Set default方式 :(在可视化工具SQLyog中可能显示空白):父表有变更时,子表将外键列设置成一个默认的值,但Innodb不能识别
  • 如果没有指定等级,就相当于Restrict方式。所以默认情况下,我们不能直接对主表中的数据进行更新和删除操作
  • 对于外键约束,最好是采用: ON UPDATE CASCADE ON DELETE RESTRICT 的方式。(对主表中的数据更新时,同时更新从表中的数据,对主表中的数据删除时,将从表对应数据的列设为NULL)

删除外键约束

  • 流程如下
1
2
3
4
5
6
7
8
9
10
11
-- 1. 查看约束名和删除外键约束
SELECT *
FROM information_schema.table_constraints -- 查看某个表的约束名
WHERE table_name = '表名称';

ALTER TABLE 从表名
DROP FOREIGN KEY 外键约束名;

-- 2. 查看索引名和删除索引
SHOW INDEX FROM 表名称; -- 查看某个表的索引名
ALTER TABLE 从表名 DROP INDEX 索引名;

开发场景

  • 如果两个表之间有关系(一对一、一对多),比如:员工表和部门表(一对多),它们之间是否一定要建外键约束?
    • 不是的
  • 建和不建外键约束有什么区别?
    • 建外键约束,你的操作(创建表、删除表、添加、修改、删除)会受到限制,从语法层面受到限制。例如:在员工表中不可能添加一个员工信息,它的部门的值在部门表中找不到。
    • 不建外键约束,你的操作(创建表、删除表、添加、修改、删除)不受限制,要保证数据的 引用完整性 ,只能依 靠程序员的自觉 ,或者是 在Java程序中进行限定 。例如:在员工表中,可以添加一个员工的信息,它的部门指定为一个完全不存在的部门。
  • 那么建和不建外键约束和查询有没有关系?
    • 没有

在 MySQL 里,外键约束是有成本的,需要消耗系统资源。对于大并发的 SQL 操作,有可能会不适合。比如大型网站的中央数据库,可能会 因为外键约束的系统开销而变得非常慢 。所以, MySQL 允许你不使用系统自带的外键约束,在 应用层面 完成检查数据一致性的逻辑。也就是说,即使你不用外键约束,也要想办法通过应用层面的附加逻辑,来实现外键约束的功能,确保数据的一致性。

阿里开发规范

强制】不得使用外键与级联,一切外键概念必须在应用层解决。

说明:(概念解释)学生表中的 student_id 是主键,那么成绩表中的 student_id 则为外键。如果更新学生表中的 student_id,同时触发成绩表中的 student_id 更新,即为级联更新。外键与级联更新适用于 单机低并发 ,不适合 分布式高并发集群 ;级联更新是强阻塞,存在数据库 更新风暴 的风险;外键影响数据库的 插入速度

CHECK 约束

作用

检查某个字段的值是否符号xx要求,一般指的是值的范围

关键字

  • CHECK

说明:MySQL 5.7 不支持

MySQL5.7 可以使用check约束,但check约束对数据验证没有任何作用。添加数据时,没有任何错误或警告
但是在MySQL 8.0中可以使用CHECK约束了。

DEFAULT 约束

作用

给某个字段/某列指定默认值,一旦设置默认值,在插入数据时,如果此字段没有显式赋值,则赋值为默认值。

关键字

  • DEFAULT

如何给字段加默认值

  • 建表时
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-- 说明:默认值约束一般不在唯一键和主键列上加
CREATE TABLE 表名称(
字段名 数据类型 PRIMARY KEY,
字段名 数据类型 UNIQUE KEY NOT NULL,
字段名 数据类型 UNIQUE KEY,
字段名 数据类型 NOT NULL DEFAULT 默认值,
);

CREATE TABLE 表名称(
再举例:
字段名 数据类型 DEFAULT 默认值 ,
字段名 数据类型 NOT NULL DEFAULT 默认值,
字段名 数据类型 NOT NULL DEFAULT 默认值,
PRIMARY KEY(字段名),
UNIQUE KEY(字段名)
);
  • 建表后
1
2
3
4
5
6
7
-- 如果这个字段原来有非空约束,你还想保留非空约束,那么在加默认值约束时,也得保留非空约束,否则非空约束就被删除了
ALTER TABLE 表名称
MODIFY 字段名 数据类型 DEFAULT 默认值; -- 没加NOT NULL,非空约束就没了

-- 同理,在给某个字段加非空约束也一样,如果这个字段原来有默认值约束,你想保留,也要在modify语句中保留默认值约束,否则就删除了
ALTER TABLE 表名称
MODIFY 字段名 数据类型 DEFAULT 默认值 NOT NULL; -- 如果想保留非空约束,后面记得加上

如何删除默认值约束

1
2
3
4
5
6
7
-- 删除默认值约束,也不保留非空约束
ALTER TABLE 表名称
MODIFY 字段名 数据类型 ;

-- 删除默认值约束,保留非空约束
ALTER TABLE 表名称
MODIFY 字段名 数据类型 NOT NULL;

思考题

  • 为什么建表时,加 not null default 或 default 0
    • 不想让表中出现null值。
  • 为什么不想要 null 的值
    • 不好比较。null是一种特殊值,比较时只能用专门的is null 和 is not null来比较。碰到运算符,通常返回null。
    • 效率不高。影响提高索引效果。因此,我们往往在建表时 not null default ‘’ 或 default 0
  • 带AUTO_INCREMENT约束的字段值是从1开始的吗?
    • 在MySQL中,默认AUTO_INCREMENT的初始值是1,每新增一条记录,字段值自动加1。设置自增属性(AUTO_INCREMENT)的时候,还可以指定第一条插入记录的自增字段的值,这样新插入的记录的自增字段值从初始值开始递增,如在表中插入第一条记录,同时指定id值为5,则以后插入的记录的id值就会从6开始往上增加。添加主键约束时,往往需要设置字段自动增加属性。
  • 并不是每个表都可以任意选择存储引擎?
    • 外键约束(FOREIGN KEY)不能跨引擎使用。
    • MySQL支持多种存储引擎,每一个表都可以指定一个不同的存储引擎,需要注意的是:外键约束是用来保证数据的参照完整性的,如果表之间需要关联外键,却指定了不同的存储引擎,那么这些表之间是不能创建外键约束的。所以说,存储引擎的选择也不完全是随意的。

基础练习

练习一

  • 准备工作,先根据下面的代码创建数据库test04_emp,两张表emp2和dept2
1
2
3
4
5
6
7
8
9
10
11
12
13
CREATE DATABASE test04_emp;

USE test04_emp;

CREATE TABLE emp2(
id INT,
emp_name VARCHAR(15)
);

CREATE TABLE dept2(
id INT,
dept_name VARCHAR(15)
);
  • 1.向表emp2的id列中添加PRIMARY KEY约束
1
2
ALTER TABLE emp2 
MODIFY id INT PRIMARY KEY;
1
2
ALTER TABLE emp2 
ADD PRIMARY KEY(id);
  • 2.向表dept2的id列中添加PRIMARY KEY约束
1
2
ALTER TABLE dept2 
MODIFY id INT PRIMARY KEY;
1
2
ALTER TABLE dept2 
ADD PRIMARY KEY(id);
  • 3.向表emp2中添加列dept_id,并在其中定义FOREIGN KEY约束,与之相关联的列是dept2表中的id列。
1
2
3
4
5
6
7
8
-- 添加列dept_id
ALTER TABLE emp2
ADD COLUMN dept_id INT;

-- 建立外键约束
ALTER TABLE emp2
ADD FOREIGN KEY(dept_id)
REFERENCES dept2(id);

练习二

  • 承接《第11章_数据处理之增删改》的综合案例。

  • 1、创建数据库test01_library
1
CREATE DATABASE IF NOT EXISTS test01_library;
  • 2、创建表 books,表结构如下:
字段名 字段说明 数据类型
id 书编号 INT
name 书名 VARCHAR(50)
authors 作者 VARCHAR(100)
price 价格 FLOAT
pubdate 出版日期 YEAR
note 说明 VARCHAR(100)
num 库存 INT
1
2
3
4
5
6
7
8
9
CREATE TABLE books(
id INT,
`name` VARCHAR(50),
`authors` VARCHAR(100),
price FLOAT,
pubdate YEAR,
note VARCHAR(100),
num INT
);
3、使用ALTER语句给books按如下要求增加相应的约束
字段名 字段说明 数据类型 主键 外键 非空 唯一 自增
id 书编号 INT(11)
name 书名 VARCHAR(50)
authors 作者 VARCHAR(100)
price 价格 FLOAT
pubdate 出版日期 YEAR
note 说明 VARCHAR(100)
num 库存 INT(11)
1
2
3
4
5
6
7
8
9
10
11
12
-- 给id增加主键约束(主键约束是非空且唯一的)
ALTER TABLE books ADD PRIMARY KEY(id);

-- 给id字段增加自增约束
ALTER TABLE books MODIFY id INT AUTO_INCREMENT

-- 给其余字段添加非空约数
ALTER TABLE books name VARCHAR(50) NOT NULL;
ALTER TABLE books `authors` VARCHAR(100) NOT NULL;
ALTER TABLE books price FLOAT NOT NULL;
ALTER TABLE books pubdate DATE NOT NULL;
ALTER TABLE books num INT NOT NULL;

练习三

  • 1. 创建数据库test04_company
1
CREATE DATABASE test04_company;
  • 2. 按照下表给出的表结构在test04_company数据库中创建两个数据表offices和employees
  • offices 表

字段名 数据类型 主键 外键 非空 唯一 自增
officeCode INT(10)
city VARCHAR(50)
address VARCHAR(50)
country VARCHAR(50)
postalCode VARCHAR(15)
  • employees 表
字段名 数据类型 主键 外键 非空 唯一 自增
employeeNumber INT(11)
lastName VARCHAR(50)
firstName VARCHAR(50)
mobile VARCHAR(25)
officeCode INT(10)
jobTitle VARCHAR(50)
birth DATETIME
note VARCHAR(255)
sex VARCHAR(5)
1
2
3
4
5
6
7
CREATE TABLE offices(
officeCode INT(10) PRIMARY KEY,
city VARCHAR(50) NOT NULL,
address VARCHAR(50),
country VARCHAR(50) NOT NULL,
postalCode VARCHAR(15) UNIQUE
);
1
2
3
4
5
6
7
8
9
10
11
12
CREATE TABLE employees(
employeeNumber INT(11) PRIMARY KEY AUTO_INCREMENT,
lastName VARCHAR(50) NOT NULL,
firstName VARCHAR(50) NOT NULL,
mobile VARCHAR(25) UNIQUE,
officeCode INT(10) NOT NULL,
jobTitle VARCHAR(50) NOT NULL,
birth DATETIME NOT NULL,
note VARCHAR(255),
sex VARCHAR(5),
FOREIGN KEY(officeCode) REFERENCES offices(officeCode)
);
3. 将表employees的mobile字段修改到officeCode字段后面
1
2
ALTER TABLE employees
MODIFY mobile VARCHAR(25) AFTER officeCode;
4. 将表employees的birth字段改名为employee_birth
1
2
ALTER TABLE employees
MODIFY employee_birth DATETIME NOT NULL; -- 别忘了NOT NULL,原本是NOT NULL,只改个字段名,非空权限记得保留
5. 修改sex字段,数据类型为CHAR(1),非空约束
1
2
ALTER TABLE employees
MODIFY sex CHAR(1) NOT NULL;
6. 删除字段note
1
2
ALTER TABLE employees
DROP note;
7. 增加字段名favoriate_activity,数据类型为VARCHAR(100)
1
2
ALTER TABLE employees
ADD favoriate_activity VARCHAR(100);
8. 将表employees名称修改为employees_info
1
2
RENAME TABLE employees
TO employee_info;

拓展练习

挖个坑,等以后复习的时候 再来写