16.3 数据库设计与查询语句

1 数据库基本概念

1、关系:两个表的公共字段

2、行:也称记录,也称实体

3、列:也称字段,也称属性

就表结构而言,表分为行和列;
就表数据而言,分为记录和字段;
就面向对象而言,一个记录就是一个实体,一个字段就是一个属性。

4、数据冗余:相同的数据存储在不同的地方

脚下留心:
1、冗余只能减少,不能杜绝。
2、减少冗余的方法是分表
3、为减少数据查找的麻烦,允许数据有一定的冗余

5、数据完整性:正确性+准确性=数据完整性

正确性:数据类型正确
准确性:数据范围要准确

思考:学生的年龄是整型,输入1000岁,正确性和准确性如何?

答:正确的,但不准确的

思考:年龄是整形的,收入了字符串,正确性和准确性如何?

答:不正确

2 实体和实体之间的关系

1、一对一

2、一对多 (多对一)

3、多对多 1536975724695

2.1 一对多 1:N

1、主表中的一条记录对应从表中的多条记录。

2、一对多和多对一是一样的

1536976096582

如何实现一对多?

答:主键和非主键建关系

问题:说出几个一对多的关系?

答:班级表和学生表、 班主表和学生表

2.2 一对一(1:1)

1、主表中的一条记录对应从表中的一条记录

1536976513236

如何实现一对一?

主键和主键建关系就能实现一对一。

2.3 多对多(N:M)

主表中的一条记录对应从表中的多条记录,从表中的一条记录对应主表中的多条记录

班级和讲师的关系

1536977577667

如何实现多对多?

答:建立第三张表来保存关系。

问题:说出几个多对多的关系?

1、科目表和学生表的关系 2、商品表和订单表 3、游戏目录表和玩家表

3 数据库设计的步骤

1536977906540

3.1 数据库设计具体步骤

1、 收集信息:与该系统有关人员进行交流、坐谈,充分理解数据库需要完成的任务

2、 标识对象(实体-Entity)标识数据库要管理的关键对象或实体

3、 标识每个实体的属性(Attribute)

4、 标识对象之间的关系(Relationship)

5、 将模型转换成数据库

6、 规范化

3.2 绘制E-R图

E-R(Entity-Relationship)实体关系图

E-R图的语法

1536978470142

绘制E-R图

1536978565499

3.3 将E-R图转成表

1、 实体转成表,属性转成字段

2、 如果没有合适的字段做主键,给表添加一个自动增长列做主键。

3.4 例题

1、项目需求

2、标识对象

3、标识对象的属性

1536978271446

4、建立关系,绘制E-R图

1536978734804

5、将E-R图转出表结构

4 数据规范化

Codd博士定义了6个范式来规范化数据库,范式由小到大来约束,范式越高冗余越小,但表的个数也越多。实验证明,三范式是性价比最高的。

4.1 第一范式:确保每列原子性

第一范式确保每个字段不可再分

1536979522448

思考:如下表设计是否合理?

1536979672041

不合理。不满足第一范式,上课时间可以再分

1536979718323

思考:地址包含省、市、县、地区是否需要拆分?

答:如果仅仅起地址的作用,不需要统计,可以不拆分;如果有按地区统计的功能需要拆分。

在实际项目中,建议拆分。

4.2 第二范式:非键字段必须依赖于键字段

一个表只能描述一件事

1536980482113

思考:如下表设计是否合理?

1536980574792

4.3 第三范式:消除传递依赖

在所有的非键字段中,不能有传递依赖

1536981861980

下列设计是否满足第三范式?

1536982061259

不满足,因为语文和数学确定了,总分就确定了。

4.4 数据库设计的例题

1、需求

2、工资表

1536982976983

3、将工资表转成数据库表

1536983011535

4、这个表存在的问题

5、规范化表

1536983332419
1536983422611

更改如下:

1536983406042

5 查询语句

5.1 字段表达式

通过as给字段取别名

多学一招:as可以省略

5.2 from子句

from:来自,from后面跟的是数据源。数据源可以有多个。返回笛卡尔积。

插入测试表

测试多个数据源

5.3 dual表

dual表是一个伪表。在有些特定情况下,没有具体的表的参与,但是为了保证select语句的完整又必须要一个表名,这时候就使用伪表。

5.4 where子句

where后面跟的是条件,在数据源中进行筛选。返回条件为真记录

MySQL支持的运算符

  1. > 大于

  2. <小于

  3. >=

  4. <=

  5. =

  6. !=

  7. and 与

  8. or 或

  9. not 非

思考:如下代码输出什么

思考:如何查找北京和上海的学生

5.5 in | not in

上面的查询上海和北京的学生的SQL可以通过in语句来实现

练习:

1、查找学号是s25301,s25302,s25303的学生

2、查找年龄是18,19,20的学生

3、查找不是北京和上海的学生

5.6 between…and|not between…and

查找某个范围的记录

1、查找年龄在18~20之间的学生

2、查找年龄不在18~20之间的学生

5.7 is null | is not null

脚下留心:查询一个为空的字段不能用等于,必须用is null

查找缺考的学生

查找参加考试的学生

5.8 聚合函数

  1. sum() 求和

  2. avg() 求平均值

  3. max() 求最大值

  4. min() 求最小值

  5. count() 求记录数

5.9 通配符

  1. _ [下划线] 表示任意一个字符

  2. % 表示任意字符

练习

1、满足“T_m”的有(A、C)

A:Tom B:Toom C:Tam D:Tm E:Tmo

2、满足“Tm”的有(B、C )

A:Tmom B:Tmmm C:T1m2 D:Tmm E:Tm

3、满足“张%”的是(A、B、C、D)

A:张三 B:张三丰 C:张牙舞爪 D:张 E:小张

4、满足“%诺基亚%”的是(A、B、C、D)

A:诺基亚2100 B:2100诺基亚 C:把我的诺基亚拿过来 D:诺基亚

5.10 模糊查询(like)

5.11 order by排序

asc:升序【默认】

desc:降序

多列排序

思考如下代码表示什么含义

5.12 group by 【分组查询】

将查询的结果分组,分组查询目的在于统计数据。

1536999666442

通过group_concat()函数将同一组的值连接起来显示

1536999889281
1536999987356

多列分组

5.13 having条件

例题

思考如下语句是否正确 1537001246956

1537001432304

having和where的区别:

where是对原始数据进行筛选,having是对记录集进行筛选。

5.14 limit

语法:limit 起始位置,显示长度

起始位置可以省略,默认是从0开始

例题:找出班级总分前三名

多学一招:limit在update和delete语句中也是可以使用的。

5.15 查询语句中的选项

查询语句中的选项有两个:

1、 all:显示所有数据 【默认】

2、 distinct:去除结果集中重复的数据

6 union(联合)

插入测试数据

6.1 union的使用

作用:将多个select语句结果集纵向联合起来

例题:查询上海的男生和北京的女生

6.2 union的选项

union的选项有两个

1、 all:显示所有数据

2、 distinct:去除重复的数据【默认】

默认是去重复的

6.3 union的注意事项

1、 union两边的select语句的字段个数必须一致

2、 union两边的select语句的字段名可以不一致,最终按第一个select语句的字段名。

3、 union两边的select语句中的数据类型可以不一致。

7 多表查询分类

将多个表的数据横向的联合起来。 1、 内连接 2、 外连接 a) 左外连接 b) 右外连接 3、 交叉连接 4、 自然连接

7.1 内连接【inner join】

例题

脚下留心:显示公共字段需要指定表名 1537061664763

1537061715978

7.2 左外连接【left join】

以左边的表为标准,如果右边的表没有对应的记录,用NULL填充。

例题

7.3 右外连接【right join】

以右边的表为标准,如果左边的表没有对应的记录,用NULL填充。

例题

7.4 交叉连接【cross join】

插入测试数据

1、如果没有连接表达式返回的是笛卡尔积

2、如果有连接表达式等价于内连接

7.5 自然连接【natural】

自然连接又分为:

  1. 自然内连接 natural join

    . 自然左外连接 natural left join

    . 自然右外连接 natural right join

例题:

自然连接结论:

  1. 表连接通过同名的字段来连接的

  2. 如果没有同名的字段返回笛卡尔积

  3. 会对结果进行整理,整理的规则如下

    a) 连接字段保留一个

    b) 连接字段放在最前面

    c) 左外连接左边在前,右外连接右表在前

7.6 using()

  1. 用来指定连接字段。

  2. using()也会对连接字段进行整理,整理方式和自然连接是一样的。

8 子查询

语法

  1. 外面的查询称为父查询,括号中的查询称为子查询

  2. 子查询为父查询提供查询条件

8.1 例题

1、查找笔试80分的学生

2、查找笔试最高分的学生

8.2 in|not in子查询

用于子查询的返回结果多个值。

1、查找笔试成绩及格的同学

2、查询不及格的同学

3、查询没有通过的同学(不及格,缺考)

8.3 exists和not exists

1、 如果有人笔试超过80分就显示所有的学生

2、 如果没有人超过80分就显示所有的学生

8.4 子查询分类

1、标量子查询:子查询返回的结果就一个

2、列子查询:子查询返回的结果是一个列表

3、行子查询:子查询返回的结果是一行

例题:查询成绩最高的男生和女生

4、表子查询:子查询返回的结果当成一个表

例题:查询成绩最高的男生和女生

9 补充技术

9.1 insert…select…

选择一个表的数据插入到另外的表中。

9.2 on duplicate key update

在插入数据的时候,如果插入的数据不满足主键约束或唯一约束则执行更新操作。

Last updated

Was this helpful?