MySQL_表设计原则

内容

  1. 给你一个场景,让你设计表。
  2. 关系型数据库的范式设计。
  3. 一对一/一对多实体关系的表设计原则
  4. 多对多实体关系的表设计原则
  5. 总结 - 表设计三要素

表间的关系

现实中,表与表之间的关系无非就三种:一对一、一对多、多对多。

如何设计表之间的关联关系?

一对一

举个例子:用户User和身份信息Info的关系,一个用户对应一个身份信息。两张表是一对一的关系。

  • 用户User
uid(主键、自增) name age sex
1000 zhang 20 M
1020 liu 21 W
2010 wang 22 M
  • 身份信息Info
cardid addrinfo
112233 china
334455 japan
556677 canada

目前来看,身份信息表和用户表完全对应不上。

需要在身份信息表加一个关联父表主键的字段uid,才能和用户表对应上

uid cardid addrinfo
1000 112233 china
1020 334455 japan
2010 556677 canada

现在,两个表之间的关联就是靠Info表的uid建立起来的,即Info表的uid字段关联了父表的主键,Info表的uid在逻辑上实际上就是外键,Info叫做子表,User叫做父表。子表的外键和父表的主键的数据类型必须一致,字段名无所谓。

mysql的性能瓶颈主要集中在磁盘IO,出于对性能的优化考虑,我们现在不会在sql层明确指出这是一个外键,不会把外键的约束工作分配给mysql。而是把外键的处理我们放到应用层代码。以让sql处理更核心的业务。

使表之间能够一对一关联起来的做法:在子表中增加一列,与父表的主键关联。

1
select * from info where uid=2010;	#如此就相当于间接查到“王”的身份信息

一对多/多对多

举个例子:电商平台。有三个实体:用户User、商品Product、订单Order。

分析

  • 用户 - 商品:在用户购买商品之前,它们之间没有直接的关联关系
  • 用户 - 订单:一对多的关系
  • 商品 - 订单:多对多的关系

表设计

  • 用户User表
uid name age sex
1000 zhang 20 M
1020 liu 21 W
2010 wang 22 M
  • 商品Product表
pid pname price amount
1 phone 600.0 100
2 laptop 2000.0 50
3 battery 10.0 200
  • 订单Order表
orderid pid number money totalprice addrinfo
O1000 1 1 600.0 4640.0 西安工业大学
O1000 2 2 4000.0 4640.0 西安工业大学
O1000 3 4 40.0 4640.0 西安工业大学
O2000 2 1 2000.0 2000.0 陕西科技大学

用户和订单 - 一对多

订单中没有用户的信息,对应不上是哪个用户的订单。

则需要给订单加一个用户id字段,需与主表的主键关联,类型必须一致。即可与用户对应。

orderid uid pid number money totalprice addrinfo
O1000 1000 1 1 600.0 4640.0 西安工业大学
O1000 1000 2 2 4000.0 4640.0 西安工业大学
O1000 1000 3 4 40.0 4640.0 西安工业大学
O2000 2010 2 1 2000.0 2000.0 陕西科技大学

商品和订单 - 多对多

目前的订单表的设计是有很多问题的,信息冗余过多。如果某用户在同一订单中购买了多种商品,则orderid、uid、totalprice和addrinfo都是一致的,为每一种商品都单列一条记录,冗余过多。

冗余带来的问题有很多,其中最大的问题是,如果用户对订单进行增删改查,则有可能影响整个有关此订单的所有记录,修改代价高。

如果订单(Order)表像下面这样,就很简洁了。这就不存在冗余了。如果需要更改订单,不用删除多行记录,只需修改一次。

orderid uid totalprice addrinfo
O1000 1000 4640.0 西安工业大学
O2000 2010 2000.0 陕西科技大学

但是还要知道订单的内容,需要一个中间表 - 订单内容OrderList。

orderid pid number money
O1000 1 1 600.0
O1000 2 2 4000.0
O1000 3 4 40.0
O2000 2 1 2000.0

由此设计,商品表和订单表则不会出现数据冗余。

总结

在进行表的设计时,考虑三个问题

  1. 表字段数据类型的斟酌
  2. 完整性约束条件的规范
  3. 实体关系对应的表设计原则

实体之间的关系,无非是一对一、一对多、多对多。

一对一、一对多中,子表和父表的关联可由子表增加一列字段来关联父表的主键。

而多对多关系中,除了增加一列字段来关联父表,还需要增加一个中间表来消除冗余。

MySQL_运算符

内容

  1. 算数运算符
  2. 逻辑运算符
  3. 比较运算符

算术运算符

运算符 作用
+ 加法
- 减法
* 乘法
/DIV 除法,返回商
%MOD 除法,返回余数
  • 注意
    • 计算时,需要注意当时的数据类型取值范围是否合适,以免越界导致业务出错

示例

1
update user set age=age+1;

逻辑运算符

运算符 作用
NOT! 逻辑非
AND&& 逻辑与
OR或`

比较运算符

运算符 作用
= 等于
<>!= 不等于(<>在未来可能会被淘汰)
<=> NULL安全的等于(NULL-safe)
< 小于
<= 小于等于
> 大于
>= 大于等于
运算符 作用
BETWEEN 存在于指定范围
IN 存在于指定集合
IS NULL 为NULL
IS NOT NULL 不为NULL
LIKE 通配符匹配
REGEXPRLIKE 正则表达式匹配
  • 注意
    • 判空不要写=NULL,而是要写IS NOT NULLIS NULL;判空经常出现在左连接、右连接中的外键查询。
    • 通配符与索引的关系?
      • LIKE通配符不一定会用到索引,需要看通配符加的地方,如果通配符在中间、末尾则能用到;但是如果加到最开始则不会用到。

示例

1
2
select * from user where age between 20 and 22;
select * from user where score in (99.0, 100.0);
1
select * from user where score IS NOT NULL;
1
2
select * from user where name like 'zhang%';	#zhang开头的任何字符串
select * from user where name like 'zhang_'; #下划线是占位通配符,只能匹配后面只有一个字符的

综合示例

下面这个查询语句用到了多个运算符:sex='M'andscore>=90.0

1
select * from where sex='M' and score>=90.0;