数据库概念
基本概念
数据:描述数据的符号。
数据库 (DB):
- 概念:长期储存、有组织、可共享、大量数据集合
- 基本特征:
- 数据按一定的数据模型组织、描述和储存
- 可为各种用户共享
- 冗余度较小
- 数据独立性较高
- 易扩展
- 可共享
数据库管理系统 (DBMS)
数据库系统 (DBS) = 数据库+数据库管理系统(和应用开发工具)+应用程序+数据库管理员
数据库的发展阶段
阶段 | 人工管理 | 文件系统 | 数据库系统 |
---|
数据保存 | 不保存 | 长期保存 | 长期保存 |
数据管理者 | 人工管理 | 文件系统 | 数据库管理系统 |
面向对象 | 某一程序 | 某一应用 | 现实世界 |
共享程度 | 无 | 差 | 高 |
冗余程度 | 很大 | 大 | 低 |
独立性 | 无 | 差 | 强 |
结构化 | 无 | 记录内有,无整体结构化 | 整体结构化 |
控制 | 应用程序自己控制 | 应用程序自己控制 | 由数据库管理系统控制 |
数据库系统的优点
- 整体数据的结构化(整个企业、整个数据) 这是本质区别
- 共享度高、冗余度低、易扩充
- 数据独立性高
- 数据库管理系统统一管理和控制数据
数据的独立性、安全性和完整性
数据独立性
- 物理独立性:用户的应用程序与数据库中数据的 物理存储 是相互独立的。
- 逻辑独立性:用户的应用程序与数据库的 逻辑结构 是相互独立的。
数据安全性
概念:保护数据防止不合法使用导致:
存取控制:
- 自主存取控制:GRANT 语句,用户灵活控制
- 强制存取控制:对数据库对象标以保密级别,每个用户授权相应级别的许可证
保密级别:TS(绝密)>=S(机密)>=C(可信)>=P(公开)
数据完整性
正确性、有效性、相容性
数据模型
两类模型
第一类:
第二类:
- 逻辑模型:层次模型、网状模型、关系模型、面向对象数据模型、对象关系数据模型、半结构化数据模型
- 物理模型
组成要素
- 数据结构
- 数据操作
- 数据的完整性约束条件
三层模式
模式
- 模式是对数据库全体数据逻辑结构和特征的描述
- 模式相对稳定,实例相对变动
三层模式结构
结构 | SQL 结构 | 介绍 |
---|
外模式 | 基本表、视图 | 数据库用户看见的局部数据的逻辑结构和特征,针对应用程序 |
模式 | 基本表 | 全体数据的逻辑结构和特征,所有用户的公共数据视图 |
内模式 | 存储文件 | 数据库内部组织数据的方式,一个数据库只有一个内模式 |
模式映像
- 外模式/模式映像:修改模式可以让外模式保持不变,保证了数据与应用程序的 逻辑独立性
- 模式/内模式映像:修改内模式可以让模式保持不变,保证了数据与程序的 物理独立性
SQL
功能
结构
- 基本表:一个关系对应一个基本表
- 存储文件:一个或多个基本表、索引对应一个存储文件
- 视图:从一个或多个基本表中导出的虚表,存储文件不存放其数据,用户可以在视图上继续定义视图。
视图的作用
- 简化操作
- 多角度看数据
- 保护机密数据
- 更清晰的表达查询
关系数据库理论
基本概念
- 关系:一张二维表,准确的定义:集合D1...Dn 笛卡尔积的 子集,
n
称为目或度。- 关系的表示:
关系名(属性名1, 属性名2, ...)
,主键用下划线标示,外键用波浪线标示 。
- 元组:表中的一行,行的次序可任意交换。
- 属性:表中的一列;每一列的分量数据类型相同,来自同一个域(同质性);列的次序可任意交换。
- 码:唯一确定元组的某个属性组
- 候选码:唯一确定元组的某个属性组,但其子集不能;任意两个候选码不能取相同的值。
- 主码:从多个候选码中选定一个
- 主属性:候选码中的属性
- 域:具有相同数据类型的值的集合,不同的列可来自同一个域。
- 分量:元组的一个属性值,取原子值,不可再分。
- 关系数据库的型:关系数据库模式,对关系数据库的描述
- 关系数据库:关系数据库模式在某一时刻对应关系的集合
关系完整性
- 实体完整性:主码不相同、主码不为空
- 参照完整性:外码等于某个元组的主码值、外码 为空
- 用户定义的完整性:具体数据的要求
关系代数
介绍
- 传统的集合运算:并、交、差、笛卡尔积
- 专门的关系运算:选择、投影、连接、除
选择
从关系中选择某些行:σ条件(R)
投影
从关系中选择某些列:Π列1,列2(R)
连接
- 连接:从关系 R、S 中选择 A 和 B 满足条件θ 的元组,其中 A 是 R 中的一个属性组,B 是 S 中的一个属性组,⋈AθB(R,S)
- 等值连接:选取属性值相等的元组,⋈A=B(R,S)
- 自然连接:比较的分量同名+去除重复列⋈(R,S)
- 悬浮元祖:连接过程中因不满足连接条件被舍弃的元组
- 外连接:留住悬浮元组,悬浮元组的其他值填充为 NULL
- 左外连接:留住左边的悬浮元组
- 右外连接:留住右边的悬浮元组
除
关系 A 除以关系 B 得到关系 C,则关系 C 中包含所有在 A 中不在 B 中的属性及其值,且 B,C 的元组组合均在 A 中
除运算通常用于解决“选择了所有**的人”这样的问题。
理解除运算
SC 表:
StudentId | CourseId |
---|
1 | 1 |
1 | 2 |
1 | 3 |
2 | 1 |
3 | 1 |
1 | 2 |
建立一个临时表 C:
那么SC÷C 得到:
也就是选择了 1
和 2
号课程的学生。
如果将除法的结果和被除关系进行笛卡尔积,那么结果:
StudentId | CourseId |
---|
1 | 1 |
1 | 2 |
3 | 1 |
1 | 2 |
可以发现这个结果是 SC
的子集。
做除法的办法:
- 寻找 R、S 相同的几个列 C={C1,C2,…}
- 将 R 按照 C 之外的列进行分组
- 对 S 进行投影: T=ΠC1,C2,...(R)
- 对于 R 中的每一个分组,如果出现了 T 中的所有元组,则作为除法的结果之一。
- 结果除掉 R、S 相同的部分
关系优化
函数依赖的概念
函数依赖:设R(U)是属性集上的关系模式,X,Y 是 U 的子集,对于∀r∈R(U),不存在两个元组在 X 上的属性值相等,而在 Y 上的属性值不等,则称 X 函数确定 Y,即X→Y
- 例子:账号→密码,其中账号是唯一的,否则不是函数依赖
平凡函数依赖:X→Y,Y∈X
- 例子:(学号,课程号)→学号
非平凡函数依赖:X→Y,Y∈X
- 例子:(学号,课程号)→成绩
X→Y,Y→X,则X←→Y
若 Y 不函数依赖于 X,则X→Y
若X→Y,且 对于任意的 X 的真子集X′,X′→Y,则称 Y 对 X 完全函数依赖,记为X→FY
- 例子:(学号,课程号,成绩)→成绩 不是完全函数依赖,因为(学号,课程号)→成绩;
- 例子:(学号,课程号)→成绩 是完全函数依赖,因为少了任意一个都不能决定成绩
若X−>Y,但是Y 不完全函数依赖于X,则 Y 对 X 部分函数依赖,记为X→PY
若X−>Y(Y⊆X),且Y→X,Y−>Z,则称 Z 对 X 传递函数依赖,记为X→传递Z
码
候选码:K→FU
- (学号,课程号)→P(学号,课程号,成绩),即 学号, 课程号是候选码
超码:K→U,即候选码的超集,候选码的任何真子集一定不是超码。
主码:从候选码中选择一个
全码:整个属性组是码
范式
- 1NF: 分量不可再分
- 2NF: 无部分函数依赖(消除多余的候选码)
- 3NF: 消除传递依赖(将传递依赖拆分成两个)
将低范式转换成高范式的过程称为 规范化,方法是模式分解。
数据库操作
数据定义
操作对象 | 定义(CREATE ) | 删除(DROP ) | 修改(ALTER ) |
---|
模式(SCHEMA ) | CREATE SCHEMA | DROP SCHEMA | |
基本表(TABLE ) | CREATE TABLE | DROP TABLE | ALTER TABLE |
视图(VIEW ) | CREATE VIEW | DROP VIEW | |
索引(INDEX ) | CREATE INDEX | DROP INDEX | ALTER INDEX |
模式操作
模式实际上是一个命名空间。
- 创建模式
1
| CREATE SCHEMA <模式名> AUTHORIZATION <用户名> [表/视图/授权定义子句];
|
若省略模式名,则模式名为用户名。
- 删除模式
1
| DROP SCHEMA <模式名> <CASCADE|RESTRICT>;
|
- CASCADE:删除模式同时删除所有模式下的内容
- RESTRICT: 若模式下有内容,则拒绝删除
基本表操作
- 定义基本表
1 2 3 4 5 6
| CREATE TABLE <表名> ( <列名> <数据类型> <完整性约束>, [<列名> <数据类型> <完整性约束>], ..., [<表级完整性约束>,...] );
|
- 数据类型
数据类型 | 解释 |
---|
int,bigint | 整型 |
double | 浮点型 |
char(n), varchar(n) | 字符串 |
date,time,datetime | 日期 |
- 修改基本表
1 2 3 4 5 6
| ALTER TABLE <表名> [ADD [COLUMNS] <新列名> <数据类型> [完整性约束]] [ADD <表级完整性约束>] [DROP COLUMN <列名> [CASCADE|RESTRICT]] [DROP CONSTRAINT <完整性约束名> [RESTRICT|CASCADE]] [ALTER COLUMN <列名> <数据类型>]
|
- 删除基本表
1
| DROP TABLE <表名> <CASCADE|RESTRICT>;
|
- CASCADE:删除表同时删除所有模式下的内容
- RESTRICT: 若表下有内容,则拒绝删除
- 定义主键(实体完整性)
在列级上定义:
1
| create table student (id bigint primary key, sex char(2));
|
在表级上定义:
1 2 3 4 5 6
| create table score ( student_id bigint, course_id bigint, score int, primary key (student_id, course_id) );
|
添加主键后,在增加/修改数据时,自动检查其是否唯一且是否为空。
- 添加外键(参照完整性)
1 2 3 4 5 6 7 8
| create table score ( student_id bigint, course_id bigint, score int, primary key (student_id, course_id), constraint `FK_SCORE_STUDENT_ID` foreign key (student_id) references student(id), foreign key (course_id) references course(id), );
|
其中 constraint
部分是可选的,用于为完整性约束命名。
添加外键后,在增加/修改数据时,自动检查其值是否为参照列中的值,或者空。
当被参照表更新和删除时,可能破坏参照完整性,这时有一些操作可供选择:
操作 | 说明 |
---|
NO ACTION | 拒绝执行 |
CASCADE | 当被参照列数据更新,修改本表外键;当被参照外键删除时,删除对应的元组 |
SET NULL | 当被参照列信息更新/删除时, 将外键设置为空 |
1 2 3 4 5 6 7 8
| create table score ( student_id bigint, course_id bigint, score int, primary key (student_id, course_id), foreign key (student_id) references student(id) on update cascade on delete set null, foreign key (course_id) references course(id), );
|
- 添加自定义约束(用户定义的完整性)
可添加的完整性:
NOT NULL
:不允许为空值UNIQUE
:列值唯一(默认可为空)CHECK
语句:检查是否满足条件表达式
1 2 3 4 5 6
| create table student ( id bigint primary key, name varchar(20) not null , chat_token varchar(20) unique , sex char(2) check (sex in ('男', '女')) );
|
在表级添加:
1 2 3 4 5 6 7
| create table student ( id bigint primary key, name varchar(20) not null , chat_token varchar(20) unique , sex char(2), check (sex in ('男', '女')) );
|
索引操作
建立索引可提高查询效率。
- 建立索引
1 2
| CREATE [UNIQUE] [CLUSTER] INDEX <索引名> ON <表名> (列名 <ASC|DESC>,...);
|
例子:
1 2
| create unique index score_sid_cid on score (student_id asc, course_id desc);
|
- 修改索引
1 2
| ALTER INDEX <索引名> RENAME TO <新索引名>;
|
- 删除索引
视图操作
- 创建视图
1 2 3
| CREATE VIEW <视图名> [(列名,...)] AS <子查询> [WITH CHECK OPTIONS]
|
WITH CHECK OPTIONS 用于表示对视图增删改时保证数据满足视图中的条件。
- 删除视图
- 行列子集视图:视图是从一个表中选择了若干行和列,此时可对视图进行增删改操作。
- 分组视图:带聚集函数和
GROUP BY
的视图。 - 视图消解:查询时,查询语句自动转换成对基本表的查询。
数据查询
数据查询的基本格式:
1 2 3 4 5
| SELECT 列名,... FROM 表名,... [WHERE 条件表达式] [GROUP BY 列名,... [HAVING] 条件表达式 ] [ORDER BY 列表 [ASC|DESC],...]
|
选择列
- 选择全部列
- 选择指定列
1 2
| select id, name, age from student;
|
- 选择并计算
1 2
| select id, name, 2021-age from student;
|
- 定义别名
1 2
| select id, name, 2021-age birthyear from student;
|
- 列名去重:
distinct
查询学生生日1 2
| select distinct 2021-age birthyear from student;
|
条件判断
- 整数判断:
<
、>
、=
等 - 确定集合:
in <集合>
、not in <集合>
查询出生日期在2001和2002年的学生1 2 3
| select id, name, 2021-age birthyear from student where birthyear in (2001,2002);
|
- 字符匹配:
like
、not like
、=
字符匹配符:
%
匹配任意长度的字符串,长度可为 0_
匹配一个字符
查询张性学生1 2 3
| select id, name from student where name like '张%';
|
查询第二个字为华的学生1 2 3
| select id, name from student where name like '_华%';
|
查询以下划线开头的数据1 2 3
| select id, name from student where name like '\_%' escape '\';
|
- 空值查询:
is null
、is not null
使用函数
- 普通函数
函数 | 说明 |
---|
ifnull(表达式,值) | 如果表达式不为空,则返回表达式的值,否则返回自定义的值 |
- 使用聚集函数
聚集函数 | 说明 |
---|
COUNT(*) | 计数(不跳过空值) |
COUNT(列名) | 计数(跳过空值) |
SUM(列名) | 求和(跳过空值) |
AVG(列名) | 求均值(跳过空值) |
MAX(列名) | 最大值(跳过空值) |
MIN(列名) | 最小值(跳过空值) |
如果没有分组,则针对整个列,否则针对每个组的所有列。
查询平均值1 2
| select AVG(grade) from score;
|
分组查询
- 使用
group by
子句:
查询每个学生的平均值1 2 3
| select AVG(grade) from score group by student_id;
|
having
和 where
用于筛选,其中 having
针对 分组,where
针对 基本表
查询平均分及格的学生 id1 2 3
| select student_id from score group by student_id having AVG(grade) >= 60;
|
查询每个学生中,及格的成绩的平均数1 2 3 4
| select student_id, avg(grade) from score group by student_id where grade >= 60;
|
多表查询
- 在
from
子句中,可以指定多个表,如果不指定条件,则直接将两个表做笛卡尔积运算
将 score 和 student 进行笛卡尔积1 2
| select * from score, student;
|
- 在
where
指定两个表的连接条件,可以实现连接操作
将 score 和 student 进行等值连接1 2 3
| select * from score, student where score.student_id = student.id;
|
- 可以将表进行自身连接,这时需要指定别名
获取评论及其父评论1 2 3
| select * from comment c1, comment c2 where c1.father_id = c2.id
|
- 外连接
left outer join <表名> on (连接条件)
:若需要保存悬浮元组,则需要在 from
语句中使用 join
语句
查询所有学生的平均成绩,含没有选课的学生1 2 3
| select student.*, ifnull(avg(score.grade), 0) from student left outer join score on (score.student_id = student.id) group by student.id;
|
嵌套查询
- 在
where
中嵌套 select
语句。
- 相关子查询:字查询使用了父查询的数据,这种查询不可以替换成 连接 查询。
- 不相关子查询:子查询可以独立作为
select
语句,这种查询可以替换成 连接 查询。
- 使用
any
谓词
谓词 | 说明 |
---|
>ANY(子查询) | 大于最小值 |
>ALL(子查询) | 大于最大值 |
<ANY(子查询) | 小于最大值 |
<ALL(子查询) | 小于最小值 |
=ANY (子查询) | 等于某个值 |
!=ALL(子查询) | 不等于任何值 |
- 使用
exists
谓词:单独作为一个查询条件,当结果不为空则为真 - 使用
not exists
谓词:单独作为一个查询条件,当结果为空则为真
集合查询
union
并集intersect
交集except
差集
派生表查询
在 from
语句中,表名的位置可以写成另一个查询,需要定义别表别名。
数据操纵
插入
- 插入单条数据
1
| INSERT INTO <表名> [(列名,...)] VALUES (值,...),...;
|
往学生表插入数据1
| insert into student (name) values ('kaz'),('kitty');
|
- 插入查询结果
1
| INSERT INTO <表名> [(列名,...)] <SELECT语句>;
|
插入时,列名序列可省,省略时值对应列的顺序则按建表时的列的顺序来。
更新
更新数据:
1
| UPDATE <表名> SET <列名>=表达式,... [WHERE 条件表达式];
|
这个命令会将所有满足条件的数据进行更新,如果没有 where
语句,则会修改所有的元组。
学生年龄加一1
| update student set age=age+1;
|
删除
删除数据:
1
| DELETE FROM <表名> [WHERE 条件表达式];
|
这个命令会将所有满足条件的数据进行 s 删除,如果没有 where
语句,则会删除所有数据。
空值处理
出现空值的情况
- 不知道
- 不存在
- 无意义
空值运算
空值的算术运算结果为 空值 ,比较运算为 未知(Unknown)。
- 未知
U
和真T
、假F
的次序为: T
> U
> F
。 - 或运算取较高次序;与运算取较低次序;非运算
TF
反转,U
还是 U
。 - 条件运算中只有值为
True
才成立
数据控制
授权操作
- 权限
类型 | 权限 |
---|
模式(表、模式、视图、索引) | CREATE SCHEMA/TABLE/VIEW/INDEX,ALTER TABLE |
数据(表、视图、属性列) | SELECT/INSERT/UPDATE/DELETE(属性列无)/REFERENCES/ALL PRIVILEGES |
- 授权用户
1 2 3 4
| GRANT 权限,... ON <对象类型> <对象名>,... TO <用户>,... [WITH GRANT OPTION];
|
WITH GRANT OPTION 表示用户可以继续授权权限给其他人。
- 取消授权
1 2 3 4
| REVOKE 权限,... ON <对象类型> <对象名>,... FROM <用户>,... [CASCADE|RESTRICT];
|
- 创建数据库模式的权限
1 2
| CREATE USER <用户名> [WITH [DBA|RESOURCE|CONNECT]];
|
权限 | DBA | RESOURCE | CONNECT(默认) |
---|
创建用户 | √ | × | × |
创建模式 | √ | × | × |
创建基本表 | √ | √ | × |
创建视图 | √ | √ | × |
查询和操纵数据 | √ | √ | √(有权限才行) |
角色操作
- 创建角色
角色可以和用户一样进行操纵授权,也可以将角色作为权限授权给用户。
数据库编程
过程化 SQL
- 变量定义
1
| <变量名> <数据类型> [NOT NULL] [:= <初值>]
|
- 常量定义
1
| <变量名> <数据类型> CONSTANT := <初值>
|
- 赋值语句
1 2
| <变量名>:=<值> SET <变量名>=<值>
|
- 条件判断
1 2 3 4 5
| IF <条件> THEN ... ELSE ... END IF
|
- 循环
- WHILE-LOOP
1 2 3 4
| WHILE <条件> LOOP ... BREAK END LOOP
|
- FOR-LOOP
1 2 3
| FOR count IN [REVERSE] low..high LOOP ... END LOOP
|
- low 为下界,high 为上界(到不了)
- 如果
reverse
则从上界开始递减,否则从下界开始递增
- 程序格式
1 2 3 4 5 6 7
| DECLARE 声明部分 BEGIN 程序体 EXCEPTION 异常处理部分 END;
|
触发器编程
- 定义触发器
1 2 3 4 5 6
| CREATE TRIGGER <触发器名> [BEFORE|AFTER] <事件> [OF <属性列>] ON <表名> [REFERENCING <NEW|OLD> <ROW|TABLE> AS <变量名>,...] [FOR EACH <STATEMENT|ROW>] [WHEN <条件>] <程序体>;
|
FOR EACH <STATEMENT|ROW>
:定义行级(程序体针对每一行)/语句级(程序体针对每一次语句)触发器- 语句级触发器可以程序体使用
old
和 new
。
- 删除触发器
1
| DROP TRIGGER <名称> ON <表名>;
|
存储过程和函数
存储过程经过优化,运行效率高,降低通信量。
- 创建存储过程(没有返回值)
1 2
| CREATE OR REPLACE PROCEDURE <名称> ([IN|OUT] <参数名> <类型>,...) AS <程序体>;
|
- 创建函数(有返回值)
1 2
| CREATE OR REPLACE FUNCTION <名称> (<参数名> <类型>,...) RETURNS <类型> AS <程序体>;
|
- 执行存储过程/函数
1
| CALL PROCEDURE <名称> (<参数名>,...);
|
- 删除存储过程
数据库系统
事务
介绍
- 事务:一个数据库操作序列,要么全做,要么全不做
- 事务基本语句
语句 | 说明 |
---|
begin transaction | 开启事务 |
commit | 提交事务 |
rollback | 回滚事务 |
ACID 特性
- 原子性(Atomicity):要么全做,要么全不做
- 一致性(Consistency):事务的结果是从一个状态到另一个状态,而不是中间状态
- 隔离性(Isolation):一个事务不能被另一个事务干扰
- 持续性(Durability):事务提交后,对数据库的改变是永久的
故障恢复
事务内部故障
- 由于事务未完成,回滚就行
系统故障
- 已提交的事务:重做
- 未完成事务:回滚
- 已回滚的事务:不管
最终结果只看重做的事务
并发控制
三大问题
- 丢失修改:(同读写)两个或多个事务同时读取并修改同一数据,结果数据只修改了一次
- 读脏数据:(写读撤)数据在第一个事务被修改,第二个事务读取后,第一个事务回滚
- 不可重复读:(读后写)一个事务读了一个数据,另外一个事务修改了这个数据,结果导致实际值与读取值不一致
解决方案
封锁、时间戳、乐观控制法、多版本并发控制
封锁
- 排他锁(写锁,X 锁):
- 共享锁(读锁,S 锁):
- 其他事务可读(加 S 锁)
- 其他事务写入(加 X 锁)需等待加速事务撤锁
- 加锁事务可读对象
- 加锁事务如需写对象,需要再加
X
锁
三级封锁协议
graph TB
O(一级协议)
S(二级协议)-->O
T(三级协议)-->O
- 一级协议
- 定义:修改前 加 X 锁,提交或回滚时 解锁
- 解决:丢失修改
- 二级协议
- 定义:一级协议+ 读取前 加 S 锁,读完时 解锁
- 解决:丢失修改、读脏数据
- 三级协议
- 定义:一级协议+ 读取前 加 S 锁,提交或回滚时 解锁
- 解决:丢失修改、读脏数据、不可重复读
二级和三级协议都是在一级协议基础上增加的,而不是层层增加
活锁和死锁
活锁:
死锁:
- 概念:两个事务分别封锁数据,又互相请求被另外事务封锁的数据,结果两个事务互相等待
- 预防:一次封锁法(一次性加锁数据,但降低并发度)、顺序封锁法(规定数据的封锁顺序,但数据庞大、难以维护)
- 诊断:超时法(超出时间)、等待图法(出现回路)
- 解除:撤销代价最小的事务
并发调度
当并发结果与某一个串行序列执行的结果相同时,并发结果就是对的。这称为 可串行化 调度。
可能冲突的调度:其执行次序不能交换。若该调度可串行化,则称为 冲突可串行化 调度。
- Ri(x) 和Wj(x)
- Wi(x) 和Wj(x)
两段锁协议:事务分为两个阶段,这两个阶段只关注加解锁的顺序,不关注其他语句的顺序
- 拓展阶段:事务只能申请获得锁,但不能解锁
- 收缩阶段:事务只能解锁,但不能解锁
- 符合两段锁协议的所有事务都是 可串行化 的。
调度书写格式:
- 事务:用一个泳道表示
- 读数据:
Y=R(X)=结果
,结果存入临时变量 Y - 写数据:先对 X 赋值
X=Y+1
,再进行写入 W(X)
Slock X
:对 X 加读锁Xlock X
:对 X 加写锁Unlock X
:解锁 X
一个调度书写示例:
T1 |
---|
Slock B |
Y=R(B)=2 |
Unlock B |
Xlock A |
A=Y+1=3 |
W(A) |
Unlock A |
数据库设计
基本流程
- 需求分析
- 概念设计:E-R 图
- 逻辑设计:关系模式
- 物理设计
- 数据库实施
- 运维
概念结构设计
基本概念
- 实体:客观存在、相互区别的事物
- 属性:实体所具有的某一特性
- 码:唯一标识实体的属性集
- 实体型:实体的类型
- 实体集:同类型实体的集合
实体-联系图
- 矩形:实体型
- 椭圆形:属性
- 联系:菱形
E-R 图案例:
实体的联系
- 一对一(1:1):一个班 A 只能有一个班长 B,一个班长只能在一个班
- 一对多(1:n):一个班 A 有很多学生 B,一个学生只能在一个班
- 多对多(m:n):一门课 A 有很多学生 B 选,一个学生可以选多门课
一对一联系实例:
graph TB
MONITOR[学生] --1--- RE{班长}--1---CLS[班级]
一对多联系实例:
graph TB
MONITOR[学生]--1--- RE{成员}--n---CLS[班级]
多对多联系实例:
graph TB
MONITOR[学生]--m--- RE{选课} --n---CLS[课程]
RE{选课}
逻辑结构设计
E-R 图转换成模式
- 一对一关系:转换成独立关系,或者在任意一端添加外键
- 一对多关系:转换成独立关系,或者多端添加外键
- 多对多关系、三个实体型及以上之间的联系:转换成独立关系
- 相同码之间的关系可合并
模型优化
- 不是规范化程度越高,关系越优,因为关系模式太多会降低效率。
- 水平分解:将用的多的数据分解出来
- 垂直分解:把属性分解成若干个关系