键是描述数据表中某些特殊的属性列。
假设有一个学生表和一个班级表:
学生表有: 学号,身份证号,性别等属性
班级表有: 班级id,班级名等属性.
- 超键: 超键是能唯一标识数据表中的记录的属性集的集合。
超键可以是一个属性,也可以是属性组合。 如学生表中的学号可以作为学生的唯一标识, 身份证号也可以作为学生的唯一标识,那么与这2个属性任意搭配的集合, 都可以作为学生表的超键: {[学号],[身份证号],[学号,身份证号],[学号,性别],[身份证号,性别]...}等等。
- 候选键: 候选键是能唯一标识数据表中的记录的属性的集合。
可以把候选键看作是最小粒度的超键,即没有冗余的超键。 学生表中的候选键可以为:{[学号],[身份证号]}。 但是不能为{[学号,身份证号]},因为学号和身份证号同时存在就不是最小粒度了。
- 主键: 主键是能唯一标识数据表中的记录的属性列。
看起来主键和候选键区别不大。 但是候选键可以是一个集合:{[学号],[身份证号]}, 而主键是从候选键里选出一个属性出来,要么是{[学号]},要么是{[身份证号]}。(不考虑联合主键哈)
- 外键: 外键是约束一个数据表和另一个数据表表的关系的属性列。
如何确定学生在哪个班级呢?或者说如何确定某个班级有哪些学生呢? 一个班级可以有多个学生.这就属于一对多关系。 可以在学生表中加一个班级id的外键列,与班级表的班级id关联, 这样就可以确定学生与班级的关系了。
联合主键是以多个属性列共同组成的主键, 它们以组合的形式保证数据的唯一性。
- DDL(Data Define Language:数据定义语言):DDL的功能是用于定义数据库中的模式(Schema), 模式包含了表,视图,存储过程等集合。 这里准确来说应该是定义数据库的三级模式:外模式,模式(逻辑模式,概念模式)和内模式。
DDL的关键字有: CREATE , ALTER , DROP等。
- DML(Data Manipulation Language:数据操纵语言):DML的功能是用于操作数据库中的数据。
DML的关键字有: SELECT , DELETE , UPDATE , INSERT等。
- DCL(Data Control Language:数据控制语言): DCL的功能是用于设置数据库的用户权限。
DCL的关键字有: GRANT,REVOKE等。
- TCL(Transaction Control Language:事务控制语言): TCL的功能是用于管理事务。
TCL的关键字有: BEGIN , COMMIT , ROLLBACK等。
- DQL(Data Query Language:数据查询语言): 数据查询语言,它属于DML。
DQL的主要关键字就是SELECT了。
-
DROP: 删除表(包括表的所有索引和数据)或数据库。DROP属于DDL,操作不可回滚。
-
TRUNCATE: 删除表中的所有数据,如果有字段是自增的,那么该字段将重新从0开始。 TRUNCATE属于DDL,操作不可回滚。
-
DELETE: 删除表中指定的数据,如果没有指定条件,将删除所有数据。DELETE属于DML,操作可回滚。
- 第一范式: 所有字段都是不可分解的原子属性。
假设在一张用户表中有一个字段为地址。 但地址其实就不是一个原子属性, 因为地址可以分成: 国家 + 省份 + 城市 + 区域 + 街道等属性, 所以需要以最小粒度为单位设置表的属性。比如年龄,它仅仅代表年龄,并不能再分割。
- 第二范式: 第二范式在第一范式的基础上,所有属性必须依赖于主键,不能依赖部分主键,即一个表中只能存储一种数据, 不能把多种数据都存入一张表中。
一个表必须所有的非主键属性都必须依赖于主键,而且不能只依赖部分主键, 假设有一张学生教师表,字段为: 学号,学生姓名 ,教师编号,教师姓名。
学号(PK) | 学生姓名 | 教师编号(PK) | 教师姓名 |
---|---|---|---|
1 | guang19 | 1 | qsjz |
其中学号与教师编号为联合主键,学生姓名依赖于学号,而并不依赖于教师编号,教师姓名也只依赖于教师编号, 不依赖于学号,所以学生表不符合第二范式。
正确的做法是将学生教师表拆分为2张表:学生表和教师表, 并添加一张中间表来建立学生与老师的关系(一对一或一对多)。
学生表的字段为:学号,学生姓名。 教师表的字段为:教师编号,教师姓名。
学生表:
学号(PK) | 学生姓名 |
---|---|
1 | guang19 |
教师表:
教师编号(PK) | 教师姓名 |
---|---|
1 | qsjz |
中间表:
学号(PK) | 教师编号 |
---|---|
1 | 1 |
- 第三范式: 第三范式在第二范式的基础上,属性不能间接依赖于主键,必须直接依赖于主键。
假设有一张学生表的字段为: 学号,学生姓名,班级编号,班级名称。
学号(PK) | 学生姓名 | 班级编号 | 班级名称 |
---|---|---|---|
1 | guang19 | 1 | qsjz5 |
其中学号为主键,但是班级名称依赖于班级编号,班级编号再依赖于学号。 这样班级名称与学号之间并不是直接性依赖,而是传递性依赖。
可以将学生表拆分为:学生表和班级表,其中: 学生表的字段为: 学号,学生姓名,班级编号。 班级表的字段为:班级编号 , 班级名称。
学生表:
学号(PK) | 学生姓名 | 班级编号 |
---|---|---|
1 | guang19 | 1 |
班级表:
班级编号(PK) | 班级名称 |
---|---|
1 | qsjz5 |
学生表的班级编号与班级表的班级编号就属于一种外键关系了, 2张表中也不再有传递依赖性的依赖关系了。
视图是一种展示数据表特定结果的虚拟表。 它主要用来做查询结果集的展示。
数据表是存在物理文件中的,而于视图是虚拟存在的内存表。 它实际上是一条编译好的Select SQL语句,没有任何数据。 对视图的增删改查等操作实际上是对视图的基表的操作。
视图的优点主要在于可以定制用户数据,让用户关注于其自定义数据本身,而不用理会无关的数据。
视图的主要缺点在于修改限制。 虽然视图主要是用来做结果集的查询展示的, 但是仍然可以对视图做出修改的操作(实际上是对基表做出修改)。 如果一个视图由多张基表的结果集组成,那么修改操作会变得很麻烦。
当用户使用DML SQL语句操作数据库时,数据库需要编译SQL后再执行。 而存储过程则是用户为了完成特定的任务, 而预先在数据库中定义好并经过数据库编译后的一组SQL, 用户通过指定存储过程的名字和参数来调用存储过程。
存储过程类似于编程语言中的方法函数。
存储过程的优点主要在于它允许我们像编写函数一样定义SQL语句,非常的灵活。 并且存储过程是直接经过预编译直接存储在内存之中的,执行速度是很快的。
存储过程的缺点主要在于耗费数据库的资源,如果存储过程过多,那么占用的内存也是越多的。
有的文章说存储过程的可移植性差,但应用程序的技术选型不应该是预先敲定的吗?
触发器是在指定表上,当满足指定条件时会执行的SQL语句的集合。 可以把触发器看做是特殊的存储过程,不过存储过程需要手动调用, 而触发器则是满足指定条件就会被触发。
触发器的触发事件有: UPDATE,DELETE,INSERT
触发时间有:Before,After
触发器缺点同存储过程一样。
临时表与普通数据表是相似的,不过临时表只在当前的连接之中有效, 当连接断开时,临时表就被销毁了。 因此,临时表可以保存一些临时的数据。
使用SHOW TABLES命令是无法查看临时表的。
连接分为:内连接,外连接和交叉连接。
-
内连接:内连接只返回连接表的匹配的数据。
-
外连接:外连接分为:左外连接,右外连接和全外连接。
-
左外连接:左外连接会返回左表所有的行,即使右表中没有匹配的行。
-
右外连接:右外连接返回右表所有的行,即使左表中没有匹配的行。
-
全外连接:全外连接返回所有表的所有行,即使表的数据不匹配。
-
-
交叉连接:交叉连接又称为笛卡尔积,它不同于其他连接,交叉连接无需指定条件。 它将一张表的每一行与另一张表的所有行全部匹配一遍,效率非常低,而且使用交叉连接的情况较少。