产品经理从0开始学SQL(五)-表设计
目录
1、数据库约束与常见操作
2、建表规范
ps:以下讲解均基于mysql语言。
数据库约束与常见操作
一、主键
我们知道,一个表由n行记录组成。
1、概述
关系表都有一个约束:每一行记录必须要有某个字段来唯一标识,能唯一标记记录的字段,称为主键。
假设有一张学生表:t_student
id | name | class_id | mobile |
---|---|---|---|
1 | 张三 | 2 | 130xxx |
2 | 李四 | 4 | 140xxx |
3 | 陈红 | 3 | 150xxx |
上面这张表,id是主键,我们可以通过id来区分出每一个同学:
id=1是张三,id=2是李四,id=3是陈红
一个表必须要有主键。我们可以在建表的时候,用primary key标识。比如:
create table t_student ( id int, name varchar(10), primary key (id));
2、主键字段的选择
当表已经开始使用并录入数据后,最好不要再做更改了,因为表的主键可能已经在其他表里用做外键关联或者已经在业务逻辑中使用。
所以定义主键最好不要使用业务字段,业务字段发生变更的概率比较大,比如学生的手机号码、学生的身份证都是可能发生变化的。
我们可以使用默认的自增字段来做主键,比如student表的id。
也可以使用基于时间和空间生成的uuid来做主键,uuid一般是业务逻辑里面生成来动态插入数据表。
3、联合主键
主键可以使用多个字段来标记。但是不太建议使用。这样在以后处理表关系或者业务逻辑时,会增加复杂度。
二、外键
假设有一张学生表:t_student
id | name | class_id | mobile |
---|---|---|---|
1 | 张三 | 2 | 130xxx |
2 | 李四 | 4 | 140xxx |
3 | 陈红 | 3 | 150xxx |
还有一张班级表:t_class
id | class_name |
---|---|
1 | 1班 |
2 | 2班 |
3 | 3班 |
4 | 4班 |
我们已经能通过id来识别张三、李四。那么我们怎么识别张三属于哪个班级,李四属于哪个班级呢?这时我们可以使用外键。
在t_student表增加一列叫class_id来表示班级id。
我们通过关系:t_student.class_id=t_class.id可以看出,张三在1班,李四在4班,陈红在3班。
通过外键我们可以看出,这2张表是一个1对多的关系。这里的“多”指的是学生表,“1”指的是班级表,含义是一个学生只可以对应一个班级,但是一个班级可以对应多个学生。
那如果是多对多的关系该如何实现呢?假设有一张学生选修的课程表:t_course
id | course_name |
---|---|
1 | 高等数学 |
2 | 物理 |
3 | 政治 |
4 | 算法 |
一个学生可选修多门课程,一个课程也可以被多名学生选择学习。这是一个多对多的关系。
一般会通过一个中间表来实现。
我们建立一个中间表叫做:t_student_course
id | course_id | student_id |
---|---|---|
1 | 1 | 1 |
1 | 1 | 2 |
2 | 2 | 3 |
2 | 2 | 4 |
3 | 3 | 1 |
4 | 4 | 2 |
表里一般要存储2个表的主键,如上的course_id和student_id。从表中我们就可以看出,学生id=1的张三选修了两门课程,分别是数学和政治。学生id=2的李四也选修了两门课程,分别是数据和算法。
还剩下一种表关系是1对1的关系,假设还有一张学生信息明细表,存储的是学生更详细的信息的表:t_student_detail
id | student_id | address | age |
---|---|---|---|
1 | 1 | 深圳南山 | 男 |
2 | 2 | 深圳福田 | 男 |
3 | 3 | 深圳龙岗 | 女 |
我们可以看出,一个学生对应一个详细信息。但是如果t_student_detail表里面只有一个字段或者2个字段的话,根据业务情况,也可以把这些字段纳入到t_student表中。
其实上述的学生详细明细表的做法,是一个提升表查询效率的做法。当t_student表的数据量比较大的时候,而且查询学生信息可能往往只是那几个字段,就可以通过分表的方式去提升查询性能。
小结:表之间的关系有3种,分别是1对1,1对多,多对多。1对1可以通过增加一个字段或者建立另一张表通过外键关联。1对多可以通过建立另一张表通过外键关联。而多对多可以通过建立一张中间表和其他2张表的外键关联。
三、索引
索引按用途可以分为2种,一种是用于提升查询速度的查询索引,另一种是约束唯一性作用的唯一索引。
1、查询索引
一张数据表中,可能有成千上万的数据,如果想提高查询速度,那么通过给字段创建索引是提高查询速度的一种方式。
如果t_student表中,name是经常要查询的字段,那我们可以给name创建一个索引。
ALTER TABLE t_student ADD INDEX idx_name (name)
2、唯一索引
唯一索引表示的是字段的值是唯一的。
比如学生的手机号码,身份证这些业务字段,都是唯一的,如果给这些字段加上唯一索引约束,那么当你往学生表里插入重复的手机号码或者身份证时,数据库就会报错阻止你的操作,起到保护数据唯一性的作用。
对单个字段添加唯一索引:mobile字段
ALTER TABLE t_student ADD UNIQUE INDEX uni_mobile (mobile);
对多个字段添加联合唯一索引:mobile和card_id字段
ALTER TABLE t_student ADD UNIQUE INDEX uni_mobile_card (mobile,card_id);
四、默认值
我们可以给字段设置默认值,但是默认值跟数据类型必须是匹配的。比如你是一个int整型,不能设置一个字符串类型的值。
比如设置时间字段的默认值为当前时间戳:
create table t_student ( create_time timestamp default current_timestamp );
五、NOT NULL 约束
null不是数据类型,它是列的一个属性。
null表示的是空,如果你不允许你的字段值为空,则添加not null约束
比如约束学生表的名字不能为空:
create table t_student (name VARCHAR(22) NOT NULL)
建表规范
建表三范式可能大家都知道。一般建表都要遵守三范式原则。
一、第一范式
要求有主键,并且要求每一个字段都遵守原子性不可再分。
二、第二范式
满足第一范式的前提下,要求所有非主键字段完全依赖主键,不能产生部分依赖。
举个例子:假设有一张学生表:t_student
学生编号 | 老师编号 | 学生姓名 | 老师姓名 |
---|---|---|---|
s1001 | t1001 | 张三 | 叶老师 |
s1002 | t1001 | 李四 | 叶老师 |
s1003 | t1003 | 陈红 | 李老师 |
这个表以学生编号和老师编号为联合主键。
该表会出现大量的冗余,冗余字段为“学生姓名”和“教师姓名”,出现冗余主要是学生姓名部分依赖了主键的一个字段学生编号,而没有依赖教师编号,而教师姓名部分依赖了主键的一个字段教师编号,这就是第二范式部分依赖。
所以这张表是不合理的,学生和老师之间的关系应该是多对多的关系,我们应该通过建立3张表来实现,分别是
t_student(学生表)
t_teacher(老师表)
t_student_teacher(学生老师中间表)
三、第三范式
满足第二范式的前提下,所有非主键字段和主键字段之间不能产生传递依赖。某个字段依赖于主键,而有其他字段依赖于该字段。这就是传递依赖。(不详细描述了,道理跟第二范式的例子类似)
---- END ----
免费星球:建立了一个产品+技术资料库星球,每周会定期更新资料库,内容包括最新的行业报告、电子书、原型等,关注公众号并回复【星球】免费进入!
以下是星球资料部分截图:
❤️ 爱心三连击
1、看到这里了就点个在看支持下吧,你的点赞/在看/分享是我持续创作的动力。
2、关注公众号【产品的技术小课】,回复【加群】加入产品技术交流群
3、也可添加我微信【yss627144】,一起成长。