按表 14-1 建供应商表,看长度和 DECIMAL 的范围怎样限制数据,再练习在哪些列上建索引,最后观察 InnoDB 按主码聚簇存放。
MySQL 8.0 和 MySQL Workbench,机房电脑已装好。所有语句在 Workbench 的 SQL 编辑区中执行。
Ctrl+Enter 执行光标所在的一句,Ctrl+Shift+Enter 执行全部。Mac 上把 Ctrl 换成 ⌘。
输入法切到英文。表名、字段名不加引号,字符串值才用单引号。
新建一个空的 ecommerce 库。本次实验建的是练习用的表,实验二会重新建库。
-- 第 14 章实验一数据:新建一个空的 ecommerce 库 -- 整段执行一次即可,想从头再做时重新执行。 DROP DATABASE IF EXISTS ecommerce; CREATE DATABASE ecommerce DEFAULT CHARACTER SET utf8mb4; USE ecommerce;
CREATE TABLE Supplier ( supid CHAR(5) NOT NULL COMMENT '供应商编号', supname VARCHAR(40) NOT NULL COMMENT '供应商名称', email VARCHAR(40) COMMENT '电子邮箱', telephone CHAR(11) COMMENT '联系方式', PRIMARY KEY (supid) ); INSERT INTO Supplier VALUES ('01001', '华信图书公司', 'hx@163.com', '18600008965'); -- 编号多了一位,报错 1406 INSERT INTO Supplier VALUES ('010002', '东方数码公司', NULL, '13900001234');
| CHAR(5) | 定长 5 个字符。前 2 位表示省,后 3 位是序号,一个省最多 1000 家 |
| VARCHAR(40) | 变长,名称长短不一,按实际长度存放 |
| COMMENT | 字段的说明,SHOW CREATE TABLE 时能看到 |
| 报错 1406 | Data too long,值超过了字段的长度 |
CREATE TABLE price_test (price DECIMAL(9,2)); INSERT INTO price_test VALUES (9999999.99); -- 小数超过 2 位,四舍五入 INSERT INTO price_test VALUES (12.345); SELECT * FROM price_test; -- 超出范围,报错 1264 INSERT INTO price_test VALUES (10000000);
| DECIMAL(9,2) | 一共 9 位数字,其中 2 位小数,整数部分最多 7 位 |
| 12.345 | 按 2 位小数四舍五入为 12.35 |
| 报错 1264 | Out of range,超出了类型能表示的范围 |
| 金额用 DECIMAL | 按十进制精确存放,不像 FLOAT 那样有误差 |
SHOW INDEX FROM Supplier; -- 在主码上再建一个普通索引 CREATE INDEX Supplier_supid ON Supplier (supid); SHOW INDEX FROM Supplier; -- 与主码的索引重复,删掉 DROP INDEX Supplier_supid ON Supplier;
| PRIMARY | 定义主码时,MySQL 自动在主码上建立唯一索引 |
| Supplier_supid | 同一列上的第二个索引,查询用不上,还要占空间、在修改时维护 |
| DROP INDEX | 删除索引 |
INSERT INTO Supplier VALUES ('01002', '东方数码公司', 'df@163.com', '13900001234'), ('02001', '远达文具公司', 'yd@163.com', '13600007788'); EXPLAIN SELECT * FROM Supplier WHERE supname = '东方数码公司'; CREATE INDEX idx_supname ON Supplier (supname); EXPLAIN SELECT * FROM Supplier WHERE supname = '东方数码公司';
| EXPLAIN | 显示 MySQL 打算怎样执行这条查询,并不真的执行 |
| type 为 ALL | 逐行扫描全表 |
| type 为 ref,key 为 idx_supname | 通过索引直接找到符合条件的行 |
| 什么时候建 | 经常作为查询条件、取值较多、不经常修改的列 |
CREATE UNIQUE INDEX idx_email ON Supplier (email); -- 邮箱与华信图书公司相同,报错 1062 INSERT INTO Supplier VALUES ('02002', '星河电器公司', 'hx@163.com', '13700005678');
| UNIQUE INDEX | 唯一索引,既能加快查询,又保证这一列的值不重复 |
| 报错 1062 | Duplicate entry,值已经存在 |
| 空值 | 唯一索引允许有多个空值 |
CREATE TABLE cluster_test ( id INT NOT NULL, name VARCHAR(10), PRIMARY KEY (id) ); -- 故意打乱顺序插入 INSERT INTO cluster_test VALUES (30, 'c'), (10, 'a'), (20, 'b'); SELECT * FROM cluster_test;
| 聚簇 | 把码值相近的记录存放在一起。InnoDB 的表按主码聚簇存放,主码索引就是聚簇索引 |
| 查询结果 | 全表扫描时按聚簇索引的顺序读出 |
| ORDER BY | 要保证结果的顺序,仍然要写 ORDER BY |