目录
1 表与表之间的关系
一对多 | 最常用的关系 部门和员工 |
多对多 | 学生选课表 和 学生表, 一门课程可以有多个学生选择,一个学生选择多门课程 |
一对一 | 相对使用比较少。员工表 简历表, 公民表 护照表 |
2 一对多
一对多(1:n) 例如:班级和学生,部门和员工,客户和订单,分类和商品
一对多建表原则:在从表(多方)创建一个字段,字段作为外键指向主表(一方)的主键
列:一对多:一个旅游线路分类中有多个旅游线路
-- 一的一端(主表) 旅游路线分类表
CREATE TABLE tab_category(
cid INT PRIMARY KEY AUTO_INCREMENT,
cname VARCHAR(100) NOT NULL UNIQUE
)CHARACTER SET utf8;
-- 添加旅游路线分类表
INSERT INTO tab_category (cname) VALUES ('周边游'), ('出境游'), ('国内游'), ('港澳游');
SELECT * FROM tab_category;
/* 副表 旅游路线 */
CREATE TABLE tab_route(
rid INT PRIMARY KEY AUTO_INCREMENT,
rname VARCHAR(100) NOT NULL UNIQUE,
price DOUBLE,
rdate DATE,
cid INT,-- 主表中的cid属性
-- 创建外键
CONSTRAINT route_category_cid FOREIGN KEY (cid) REFERENCES tab_category(cid) -- 创建外键
ON UPDATE CASCADE ON DELETE CASCADE -- 级联操作
) CHARACTER SET utf8;
-- 添加旅游路线数据
INSERT INTO tab_route VALUES
(NULL, '【厦门+鼓浪屿+南普陀寺+曾厝垵 高铁 3 天 惠贵团】尝味友鸭面线 住 1 晚鼓浪屿', 1499,'2018-01-27', 1),
(NULL, '【浪漫桂林 阳朔西街高铁 3 天纯玩 高级团】城徽象鼻山 兴坪漓江 西山公园', 699, '2018-02-22', 3),
(NULL, '【爆款¥1699 秒杀】泰国 曼谷 芭堤雅 金沙岛 杜拉拉水上市场 双飞六天【含送签费 泰风情 广州往返 特价团】', 1699, '2018-01-27', 2),
(NULL, '【经典•狮航 ¥2399 秒杀】巴厘岛双飞五天 抵玩【广州往返 特价团】', 2399, '2017-12-23',2),
(NULL, '香港迪士尼乐园自由行 2 天【永东跨境巴士广东至迪士尼去程交通+迪士尼一日门票+香港如心海景酒店暨会议中心标准房 1 晚住宿】', 799, '2018-04-10', 4);
SELECT * FROM tab_route;
3 多对多
多对多(m:n) 例如:老师和学生,学生和课程,用户和角色
多对多关系建表原则: 需要创建第三张表,中间表中至少两个字段,这两个字段分别作为外键指向各自一方的主键
列:多对多:一个用户收藏多个线路,一个线路被多个用户收藏
/* 多对多
创建用户表 tab_user*/
CREATE TABLE tab_user(
uid INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(100) NOT NULL UNIQUE,-- 用户名长度 100,唯一,非空
PASSWORD VARCHAR(30) NOT NULL,
NAME VARCHAR(100),-- 真实姓名长度 100
birthday DATE,
sex CHAR(1) DEFAULT '男',
telephone VARCHAR(11),
email VARCHAR(100)
)CHARACTER SET utf8;
-- 添加用户表数据
INSERT tab_user VALUES
(NULL, 'cz110', 123456, '老王', '1977-07-07', '男', '13888888888', '66666@qq.com'),
(NULL, 'cz119', 654321, '小王', '1999-09-09', '男', '13999999999', '99999@qq.com');
SELECT * FROM tab_user;
/* 旅游路线*/
CREATE TABLE tab_route(
rid INT PRIMARY KEY AUTO_INCREMENT,
rname VARCHAR(100) NOT NULL UNIQUE,
price DOUBLE,
rdate DATE,
cid INT,-- 主表中的cid属性
-- 创建外键
CONSTRAINT route_category_cid FOREIGN KEY (cid) REFERENCES tab_category(cid) -- 创建外键
ON UPDATE CASCADE ON DELETE CASCADE -- 级联操作
) CHARACTER SET utf8;
-- 添加旅游路线数据
INSERT INTO tab_route VALUES
(NULL, '【厦门+鼓浪屿+南普陀寺+曾厝垵 高铁 3 天 惠贵团】尝味友鸭面线 住 1 晚鼓浪屿', 1499,'2018-01-27', 1),
(NULL, '【浪漫桂林 阳朔西街高铁 3 天纯玩 高级团】城徽象鼻山 兴坪漓江 西山公园', 699, '2018-02-22', 3),
(NULL, '【爆款¥1699 秒杀】泰国 曼谷 芭堤雅 金沙岛 杜拉拉水上市场 双飞六天【含送签费 泰风情 广州往返 特价团】', 1699, '2018-01-27', 2),
(NULL, '【经典•狮航 ¥2399 秒杀】巴厘岛双飞五天 抵玩【广州往返 特价团】', 2399, '2017-12-23',2),
(NULL, '香港迪士尼乐园自由行 2 天【永东跨境巴士广东至迪士尼去程交通+迪士尼一日门票+香港如心海景酒店暨会议中心标准房 1 晚住宿】', 799, '2018-04-10', 4);
SELECT * FROM tab_route;
/*创建中间表:收藏表 */
CREATE TABLE tab_favorite(
uid INT,-- 用户表
rid INT,-- 旅游路线表
DATE DATETIME,
PRIMARY KEY(uid,rid),-- 创建复合主键
CONSTRAINT favorite_user_uid FOREIGN KEY (uid) REFERENCES tab_user(uid),-- 创建外键
CONSTRAINT favorite_route_rid FOREIGN KEY (rid)REFERENCES tab_route(rid)
)CHARACTER SET utf8;
-- 增加收藏表数据
INSERT INTO tab_favorite VALUES
(1,1,'2018-01-01'), -- 老王选择厦门
(1,2,'2018-02-11'), -- 老王选择桂林
(1,3,'2018-03-21'), -- 老王选择泰国
(2,2,'2018-04-21'), -- 小王选择桂林
(2,3,'2018-05-08'), -- 小王选择泰国
(2,5,'2018-06-02'); -- 小王选择迪士尼
4 一对一
一对一(1:1) 在实际的开发中应用不多.因为一对一可以创建成一张表。
5 数据库设计
5.1 什么是范式
好的数据库设计对数据的存储性能和后期的程序开发,都会产生重要的影响。建立科学的,规范的数据库就需要满足一些规则来优化数据的设计和存储,这些规则就称为范式。
5.2 三大范式
关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF) 、第四范式(4NF)和第五范式(5NF,又称完美范式)。
满足最低要求的范式是第一范式(1NF)。在第一范式的基础上进一步满足更多规范要求的称为第二范式(2NF) ,其余范式以次类推。一般说来,数据库只需满足第三范式(3NF)就行了。
1NF
数据库表的每一列都是不可分割的原子数据项,不能是集合、数组等非原子数据项。即表中的某个列有多个值时,必须拆分为不同的列。简而言之,第一范式每一列不可再拆分,称为原子性。
2NF
在满足第一范式的前提下,表中的每一个字段都完全依赖于主键。所谓完全依赖是指不能存在仅依赖主键一部分的列。简而言之,第二范式就是在第一范式的基础上所有列完全依赖于主键列。当存在一个复合主键包含多个主键列的时候,才会发生不符合第二范式的情况。比如有一个主键有两个列,不能存在这样的属性,它只依赖于其中一个列,这就是不符合第二范式。
1NF表:
2NF表:
3NF
在满足第二范式的前提下,表中的每一列都直接依赖于主键,而不是通过其它的列来间接依赖于主键。
简而言之,第三范式就是所有列不依赖于其它非主键列,也就是在满足 2NF 的基础上,任何非主列不得传递依赖于主键。所谓传递依赖,指的是如果存在"A → B → C"的决定关系,则 C 传递依赖于 A。因此,满足第三范式的数据库表应该不存在如下依赖关系:主键列 → 非主键列 x → 非主键列 y
3NF表:
5.3 三大范式小结
1NF | 原子性:表中每列不可再拆分。 |
2NF | 不产生局部依赖,一张表只描述一件事情 |
3NF | 不产生传递依赖,表中每一列都直接依赖于主键。而不是通过其它列间接依赖于主键。 |