在一个空数据库中建出学生表、课程表和选课表,给它们加上约束,再插入几条数据检验约束是否起作用。
MySQL 8.0 和 MySQL Workbench,机房电脑已装好。所有语句在 Workbench 的 SQL 编辑区中执行。
Ctrl+Enter 执行光标所在的一句,Ctrl+Shift+Enter 执行全部。Mac 上把 Ctrl 换成 ⌘。
输入法切到英文。表名、字段名不加引号,字符串值才用单引号。
新建一个空的练习库 ch05_lab。第一次执行时第一句会有一条警告(库不存在),不影响。
-- 新建练习用的数据库 ch05_lab DROP DATABASE IF EXISTS ch05_lab; CREATE DATABASE ch05_lab DEFAULT CHARACTER SET utf8mb4; -- 切换到这个数据库,后面建的表都放在这里 USE ch05_lab;
| 字段 | 含义 | 数据类型 | 要求 |
|---|---|---|---|
| sno | 学号 | CHAR(10) | 主键 |
| sn | 姓名 | VARCHAR(45) | 不能为空 |
| sex | 性别 | ENUM('男','女') | 不能为空,默认为男 |
| age | 年龄 | INT | 不能为空 |
| maj | 专业 | VARCHAR(45) | 不能为空 |
| dept | 院系 | VARCHAR(45) | 不能为空 |
CREATE TABLE s ( sno CHAR(10) NOT NULL, -- 学号,固定 10 个字符 sn VARCHAR(45) NOT NULL, -- 姓名,最多 45 个字符 sex ENUM('男','女') NOT NULL DEFAULT '男', -- 性别,只能取男或女,不填时为男 age INT NOT NULL, -- 年龄,整数 maj VARCHAR(45) NOT NULL, -- 专业 dept VARCHAR(45) NOT NULL, -- 院系 PRIMARY KEY (sno) -- 学号做主键 ); -- 查看表结构,检查是否建对 DESC s;
| CREATE TABLE s ( … ); | 建一张名为 s 的表。括号里每行一个字段,字段之间用逗号隔开,最后一行后面不加逗号 |
| CHAR(10) VARCHAR(45) | 字符串类型。CHAR 长度固定,VARCHAR 按实际长度存,括号里是最多能存的字符数 |
| ENUM('男','女') | 只能从列表中取一个值 |
| NOT NULL | 这个字段不能为空 |
| DEFAULT '男' | 插入数据时不给值,就自动填“男” |
| PRIMARY KEY (sno) | 学号做主键,不能为空,也不能重复 |
| DESC s; | 查看表 s 的结构 |
| 字段 | 含义 | 数据类型 | 要求 |
|---|---|---|---|
| cno | 课程号 | CHAR(10) | 主键 |
| cn | 课程名 | VARCHAR(45) | 不能为空,不能重复 |
| ct | 课时 | INT | 可以为空 |
CREATE TABLE c ( cno CHAR(10) NOT NULL, -- 课程号 cn VARCHAR(45) NOT NULL UNIQUE, -- 课程名,不能为空,也不能重复 ct INT, -- 课时,可以为空 PRIMARY KEY (cno) -- 课程号做主键 ); -- 查看表结构 DESC c;
| UNIQUE | 唯一约束,这个字段的值不能重复 |
| ct INT | 没有写 NOT NULL,这个字段允许为空 |
| 主键与 UNIQUE | 两者都不允许重复。一张表只能有一个主键,UNIQUE 可以有多个,而且 UNIQUE 字段可以为空 |
| 字段 | 含义 | 数据类型 | 要求 |
|---|---|---|---|
| sno | 学号 | CHAR(10) | 不能为空 |
| cno | 课程号 | CHAR(10) | 不能为空 |
| score | 成绩 | DECIMAL(5,2) | 可以为空 |
CREATE TABLE sc ( sno CHAR(10) NOT NULL, -- 学号 cno CHAR(10) NOT NULL, -- 课程号 score DECIMAL(5,2), -- 成绩,共 5 位数字,其中 2 位小数 PRIMARY KEY (sno, cno), -- 学号和课程号合起来做主键 FOREIGN KEY (sno) REFERENCES s (sno), -- 学号必须在学生表中存在 FOREIGN KEY (cno) REFERENCES c (cno), -- 课程号必须在课程表中存在 CONSTRAINT ck_score CHECK (score >= 0 AND score <= 100) -- 成绩在 0 到 100 之间 ); -- 查看完整的建表语句 SHOW CREATE TABLE sc;
| DECIMAL(5,2) | 精确小数,共 5 位数字,其中 2 位是小数,最大 999.99 |
| PRIMARY KEY (sno, cno) | 学号和课程号合起来不能重复。单看学号可以重复,因为一个学生可以选多门课 |
| FOREIGN KEY (sno) REFERENCES s (sno) | 外键。sc 中的学号必须是 s 表中已有的学号 |
| CONSTRAINT ck_score CHECK (…) | 检查约束,名字叫 ck_score,条件不成立的成绩不能写入 |
| SHOW CREATE TABLE sc; | 查看完整的建表语句,能看到主键、外键和检查约束 |
把下面的语句复制到 Workbench,一句一句执行(光标放在语句上按 Ctrl+Enter),判断每一句是成功还是报错,报错是哪一种约束在起作用。INSERT 的写法第六节再讲,这里照着执行即可。
-- (1) INSERT INTO s VALUES ('s1', '王彤', '女', 18, '计算机', '信息学院'); -- (2) INSERT INTO s (sno, sn, age, maj, dept) VALUES ('s2', '苏乐', 20, '信息', '信息学院'); -- (3) INSERT INTO s (sn, age, maj, dept) VALUES ('林欣怡', 19, '信息', '信息学院'); -- (4) INSERT INTO s VALUES ('s1', '陶然', '男', 19, '自动化', '工学院'); -- (5) INSERT INTO c VALUES ('c1', '数据库系统', 56), ('c2', '数据结构', 64); -- (6) INSERT INTO c VALUES ('c3', '数据库系统', 48); -- (7) INSERT INTO sc VALUES ('s1', 'c1', 90.5); -- (8) INSERT INTO sc VALUES ('s9', 'c1', 80); -- (9) INSERT INTO sc VALUES ('s2', 'c2', 180); -- (10) SELECT * FROM s;
| 语句 | 结果 | 原因 |
|---|---|---|
| (1) | 成功 | 各字段都符合要求 |
| (2) | 成功 | 没给性别,DEFAULT 自动填为 男 |
| (3) | 报错 1364 | 没给学号,主键字段不能为空 |
| (4) | 报错 1062 | 学号 s1 已经存在,主键不能重复 |
| (5) | 成功 | 一次插入两门课程 |
| (6) | 报错 1062 | 课程名 数据库系统 已经存在,UNIQUE 不允许重复 |
| (7) | 成功 | s1 和 c1 都存在 |
| (8) | 报错 1452 | 学生表中没有 s9,外键不允许 |
| (9) | 报错 3819 | 成绩 180 超过 100,违反 CHECK 约束 ck_score |
| (10) | 显示两名学生 | s2 的性别是 男,由默认值填入 |