数据库管理系统教程
DBMS教程提供了数据库的基本和高级概念。 我们的DBMS教程专为初学者和专业人士设计。数据库管理系统是用于管理数据库的软件。
DBMS教程包括DBMS的所有主题,如介绍,ER模型,键,关系模型,连接操作,SQL,函数依赖,事务,并发控制等。
什么是数据库
数据库是相互关联数据的集合,用于有效地检索,插入和删除数据。 它还用于以表格,模式,视图和报告等形式组织数据。
例如:学校数据库组织了有关管理员,员工,学生和教师等的数据信息。使用数据库,可以轻松检索,插入和删除信息。
数据库管理系统
数据库管理系统是用于管理数据库的软件。 例如:MySQL,Oracle等是一种非常流行的商业数据库,用于不同的应用程序。
DBMS提供了一个接口来执行各种操作,如数据库创建,在其中存储数据,更新数据,在数据库中创建表等等。
它为数据库提供保护和安全性。 在多个用户的情况下,它还保持数据一致性。
DBMS允许用户执行以下任务:
- 数据定义 - 用于创建,修改和删除定义数据库中数据组织的定义。
- 数据更新 - 用于插入,修改和删除数据库中的实际数据。
- 数据检索 - 它用于从数据库中检索数据,应用程序可以将其用于各种目的。
- 用户管理 - 它用于注册和监视用户,维护数据完整性,强制执行数据安全性,处理并发控制,监视性能以及恢复因意外故障而损坏的信息。
DBMS的特征
- 它使用在服务器上建立的数字存储库来存储和管理信息。
- 它可以提供操作数据的过程的清晰逻辑视图。
- DBMS包含自动备份和恢复过程。
- 它包含ACID属性,可在发生故障时将数据维持在健康状态。
- 它可以减少数据之间的复杂关系。
- 它用于支持数据的操作和处理。
- 它用于提供数据安全性。
- 它可以根据用户的要求从不同的角度查看数据库。
DBMS的优点
- 控制数据库冗余:它可以控制数据冗余,因为它将所有数据存储在一个数据库文件中,并且记录的数据放在数据库中。
- 数据共享:在DBMS中,组织的授权用户可以在多个用户之间共享数据。
- 易于维护:由于数据库系统的集中性,它易于维护。
- 缩短时间:减少开发时间和维护需求。
- 备份:它提供备份和恢复子系统,可以从硬件和软件故障中自动备份数据,并在需要时恢复数据。
- 多用户界面:它提供不同类型的用户界面,如图形用户界面,应用程序界面
DBMS的缺点
- 硬件和软件成本:运行DBMS软件需要高速数据处理器和大内存。
- 大小:它占用大量磁盘空间和大内存来高效运行它们。
- 复杂性:数据库系统会产生额外的复杂性和要求。
- 故障影响更大:故障对数据库的影响很大,因为在大多数组织中,所有数据都存储在单个数据库中,如果数据库因电气故障或数据库损坏而损坏,则数据可能永远丢失。
学习前提条件
在学习DBMS教程之前,必须具备基本数据库的基本知识。
面向读者
我们的DBMS教程旨在帮助初学者和专业人士。
问题反馈
我们不能保证您在学习此数据库管理系统教程的过程中不会遇到任何问题。本教程中的讲解,示例和代码等只是根据作者的理解来概括写出。由于作者水平和能力有限,因此不保正所有编写的文章都准确无误。但是如果有遇到任何错误或问题,请反馈给我们,我们会及时纠正以方便后续读者阅读。
DBMS有文件系统比较
数据库管理系统(DBMS)和文件系统之间存在以下差异:
| 数据库管理系统(DBMS) | 文件系统 |
|---|---|
| DBMS是一组数据。在DBMS中,用户不需要编写过程。 | 文件系统是数据的集合。在该系统中,用户必须编写用于管理数据库的过程。 |
| DBMS提供隐藏详细信息的数据的抽象视图。 | 文件系统提供数据表示和数据存储的详细信息。 |
| DBMS提供崩溃恢复机制,即DBMS保护用户免受系统故障的影响。 | 文件系统没有崩溃机制,即,如果系统在输入某些数据时崩溃,则文件内容将丢失。 |
| DBMS提供了良好的保护机制。 | 要保护文件系统下的文件非常困难。 |
| DBMS包含各种用于存储和检索数据的复杂技术。 | 文件系统无法有效地存储和检索数据。 |
| DBMS使用某种形式的锁定来处理数据的并发访问。 | 在文件系统中,并发访问存在许多问题,例如重定向文件,而其他删除某些信息或更新某些信息。 |
DBMS架构
- DBMS设计取决于其架构。基本的客户端/服务器体系结构用于处理大量PC,Web服务器,数据库服务器和与网络连接的其他组件。
- 客户端/服务器体系结构由许多PC和工作站组成,它们通过网络连接。
- DBMS体系结构取决于用户如何连接到数据库以完成其请求。

数据库体系结构可以看作是单层或多层。但从逻辑上讲,数据库架构有两种类型:2层架构和3层架构。
1层架构
- 在此体系结构中,数据库可直接供用户使用。 这意味着用户可以直接坐在DBMS上并使用它。
- 所做的任何更改都将直接在数据库本身上完成。它不为最终用户提供便利的工具。
- 1层体系结构用于开发本地应用程序,程序员可以直接与数据库通信以获得快速响应。
2层架构
- 2层体系结构与基本客户端 - 服务器 相同。 在双层体系结构中,客户端上的应用程序可以直接与服务器端的数据库通信。 对于此交互,API类似于:ODBC,JDBC。
- 用户界面和应用程序在客户端运行。
- 服务器端负责提供以下功能:查询处理和事务管理。
- 要与DBMS通信,客户端应用程序与服务器端建立连接。

3层架构
- 3层体系结构包含客户端和服务器之间的另一层。 在此体系结构中,客户端无法直接与服务器通信。
- 客户端上的应用程序与应用程序服务器交互,该应用程序服务器进一步与数据库系统通信。
- 最终用户不知道应用程序服务器之外是否存在数据库。 数据库也不知道应用程序之外的任何其他用户。
- 3层架构用于大型Web应用程序。

三模式架构
三模式体系结构也称为ANSI/SPARC体系结构或三级体系结构。
该框架用于描述特定数据库系统的结构。
三模式体系结构还用于分离用户应用程序和物理数据库。
三模式体系结构包含三个级别。它将数据库分为三个不同的类别。
三模式架构如下:

在上图中:
- 它显示了DBMS体系结构。
- 映射用于转换各种数据库级体系结构之间的请求和响应。
- 映射对小型DBMS不利,因为它需要更多时间。
- 在外部/概念映射中,有必要将请求从外部级别转换为概念架构。
- 在概念/内部映射中,DBMS将请求从概念转换为内部级别。
1. 内部级别(Internal Level)
- 内部级别具有描述数据库的物理存储结构的内部模式。
- 内部模式也称为物理模式。
- 它使用物理数据模型。 它用于定义数据如何存储在块中。
- 物理级别用于详细描述复杂的低级数据结构。
2. 概念级别(Conceptual Level)
- 概念模式描述了概念级别的数据库设计。 概念级别也称为逻辑级别。
- 概念模式描述了整个数据库的结构。
- 概念级别描述了要在数据库中存储的数据,还描述了这些数据之间存在的关系。
- 在概念级别,隐藏了内部细节,例如数据结构的实现。
- 程序员和数据库管理员在此级别工作。
3. 外部级别(External Level)
- 在外部级别,数据库包含有时称为子模式的几个模式。子模式用于描述数据库的不同视图。
- 外部模式也称为视图模式。
- 每个视图模式都描述了特定用户组感兴趣的数据库部分,并隐藏了该用户组中的剩余数据库。
- 视图模式描述了最终用户与数据库系统的交互。
数据模型架构和实例
数据模型架构和实例
- 在特定时刻存储在数据库中的数据称为数据库的实例。
- 数据库的整体设计称为模式。
- 数据库模式是数据库的骨架结构。它表示整个数据库的逻辑视图。
- 模式(schema)包含模式对象,如表,外键,主键,视图,列,数据类型,存储过程等。
- 可以使用可视化图表来表示数据库模式。 该图显示了数据库对象以及彼此之间的关系。
- 数据库设计者设计数据库模式以帮助软件开发与数据库交互的程序员。数据库创建过程称为数据建模。
模式(schema)图只能显示模式的某些方面,如记录类型名称,数据类型和约束。 无法通过模式图指定其他方面。 例如,给定的图既不显示每个数据项的数据类型,也不显示各种文件之间的关系。
在数据库中,实际存储的数据信息经常变化。 例如,在给定的图中,只要添加新成绩或添加学生,数据库就会发生变化。特定时刻的数据称为数据库实例。

DBMS数据独立性
可以使用三模式体系结构来解释数据独立性。
数据独立性是指能够在数据库系统的一个级别修改模式而不改变下一个更高级别的模式的特征。
有两种类型的数据独立性:
1. 逻辑数据独立性
- 逻辑数据独立性是指能够在不必更改外部模式的情况下更改概念模式的特征。
- 逻辑数据独立性用于将外部级别与概念视图分开。
- 如果对数据的概念视图进行任何更改,那么数据的用户视图将不会受到影响。
- 逻辑数据独立性发生在用户界面级别。
2. 物理数据独立性
- 物理数据独立性可以定义为在不必更改概念模式的情况下更改内部模式的能力。
- 如果对数据库系统服务器的存储大小进行任何更改,那么数据库的概念结构将不会受到影响。
- 物理数据独立性用于将概念级别与内部级别分开。
- 物理数据独立性发生在逻辑接口级别。

DBMS数据库语言
DBMS具有适当的语言和接口来表达数据库查询和更新。
数据库语言可用于读取,存储和更新数据库中的数据。
数据库语言的类型

1. 数据定义语言
- DDL代表数据定义语言。它用于定义数据库结构或模式。
- 用于在数据库中创建模式,表,索引,约束等。
- 使用DDL语句,可以创建数据库的框架。
- 数据定义语言用于存储元数据的信息,如表和模式的数量,它们的名称,索引,每个表中的列,约束等。
以下是DDL下的一些任务:
Create- 用于在数据库中创建对象。Alter- 用于更改数据库的结构。Drop- 用于从数据库中删除对象。Truncate- 用于从表中删除所有记录。Rename- 用于重命名对象。Comment- 用于注释数据字典。
这些命令用于更新数据库模式,这就是它们属于数据定义语言的原因。
2. 数据操作语言
DML代表数据操作语言,它用于访问和操作数据库中的数据。它处理用户请求。
以下是DML下的一些任务:
Select- 用于从数据库中检索数据。Insert- 用于将数据插入表中。Update- 用于更新表中的现有数据。Delete- 用于删除表中的所有记录。Merge- 用于执行UPSERT操作,即插入或更新操作。Call- 用于调用结构化查询语言或Java子程序。Explain Plan- 用于解释数据的参数。Lock Table- 用于控制并发。
3. 数据控制语言
- DCL代表数据控制语言,用于检索存储或保存的数据。
- DCL执行是事务性的,还具有回滚参数。(但在Oracle数据库中,数据控制语言的执行没有回滚功能。)
以下是DCL下的一些任务:
Grant- 用于授予用户对数据库的访问权限。Revoke- 用于从用户收回权限。
以下具有Revoke授权的操作:
CONNECT,INSERT,USAGE,EXECUTE,DELETE,UPDATE和SELECT。
4. 事务控制语言
事务控制语言(TCL)用于运行DML语句所做的更改。TCL可以分组为逻辑事务。
以下是TCL下的一些任务:
Commit- 用于在数据库上保存事务。Rollback- 用于将数据库恢复为自上次提交以来的原始数据库。
DBMS ER模型概念
ER模型代表实体-关系模型。 它是一种高级数据模型。 此模型用于定义指定系统的数据元素和关系。它为数据库开发了概念设计。它还开发了一种非常简单易用的数据视图。
在ER建模中,数据库结构被描绘为称为实体关系图。
例如,假设要设计一个学校数据库。 在该数据库中,学生(student)将是具有地址,姓名,身份,年龄等属性的实体。地址(address)可以是具有诸如城市,街道名称,密码等属性的另一实体,并且它们之间将存在关系。

ER图的组成部分-

1. 实体
实体可以是任何对象,类,人或地点。 在ER图中,实体可以表示为矩形。
例如公司或组织,它有 - 经理,产品,员工,部门等可以作为一个实体。
弱实体

2. 属性

键属性

复合属性

多值属性

派生属性

3.关系
关系用于描述实体之间的关系,菱形用于表示关系。

关系类型如下:
一对一的关系

一对多的关系

多对一的关系
当左侧实体的多个实例,并且右侧的实体中只有一个实体与该关系相关联时,它称为多对一关系。

多对多的关系

ER图的表示法
可以使用符号表示数据库。 在ER图中,有许多符号用于表示基数。 这些符号如下:

DBMS映射约束
映射约束
- 映射约束是一种数据约束,表示通过关系集可以与另一个实体相关的实体的数量。
- 它在描述涉及两个以上实体集的关系集时最有用。
- 对于实体集A和B上的二元关系集R,有四种可能的映射基数。这些如下:
- 一对一(1:1)
- 一对多(1:M)
- 多对一(M:1)
- 多对多(M:M)
1. 一对一

2. 一对多

3. 多对一

4. 多对多

DBMS键
键
- 键在关系数据库中发挥的重要作用。
- 它用于唯一标识表中的记录或数据行。 它还用于建立和识别表之间的关系。
例如:在学生表中,ID用作键,因为它对每个学生都是唯一的。 在PERSON表中,passport_number,license_number,SSN是键,因为它们对每个人都是唯一的。

键类型:

1. 主键(Primary key)

2. 候选键(Candidate key)

3. 超级键(Super Key)
超级键是一组可以唯一标识元组的属性。 超级键是候选键的超集。
例如:在上面的EMPLOYEE表中,对于(EMPLOEE_ID,EMPLOYEE_NAME),两个员工的名称可以相同,但他们的EMPLYEE_ID不能相同。 因此,这种组合也可以成为键。
超级键是EMPLOYEE-ID,(EMPLOYEE_ID,EMPLOYEE-NAME)等。
4. 外键(Foreign key)
外键是表的列,用于指向另一个表的主键。
在公司中,每个员工都在特定的部门工作,员工和部门是两个不同的实体。 因此无法将该部门的信息存储在employee表中。这就要通过一个表的主键链接这两个表的原因。
例如,将DEPARTMENT表的主键Department_Id添加为EMPLOYEE表中的作为一个属性。
现在在EMPLOYEE表中,Department_Id是外键,两个表都是相关的。

DBMS泛化
泛化就像一种自下而上的方法,如果它们具有一些共同的属性,则两个或更多较低级别的实体组合形成更高级别的实体。
在泛化中,较高级别的实体也可以与较低级别的实体组合以形成更高级别的实体。
泛化更像是子类和超类系统,但唯一的区别是方法。 泛化使用自下而上的方法。
在泛化中,实体被组合以形成更通用的实体,即,子类被组合以形成超类。
例如,Faculty和Student实体可以泛化,并创建更高级别的实体Person。
DBMS限定(特别化)
DBMS限定(特别化)
- 限定(特别化)是一种自上而下的方法,它与泛化相反。 在限定(特别化)中,一个更高级别的实体可以分解为两个更低级别的实体。
- 限定(特别化)用于识别具有一些区别特征的实体集的子集。
- 通常,首先定义超类,然后定义子类及其相关属性,然后添加关系集。
例如:在员工管理系统中,EMPLOYEE实体可以根据员工在公司中扮演的角色专门作为测试人员(TESTER)或开发人员(DEVELOPER)。如下图所示 -
DBMS聚合
在聚合中,两个实体之间的关系被视为单个实体。 在聚合中,与其对应实体的关系被聚合到更高级别的实体中。
例如:中心(Center)实体提供课程(Course)实体充当关系中的单个实体,该实体与另一个实体访问者处于关系中。 在现实世界中,如果访问者访问教练中心,那么他将永远不会询问有关课程或只是关于中心,而是他会询问有关两者的询问。
ER图还原成表
可以使用符号表示数据库,并且可以将这些符号简化为表的集合。在数据库中,每个实体集或关系集都可以以表的形式表示。
将ER图转换为表有一些要点:
-
实体类型成为一个表。在给定的ER图中,
LECTURE,STUDENT,SUBJECT和COURSE形成单独的表。 -
所有单值属性都成为表的列。在
STUDENT实体中,STUDENT_NAME和STUDENT_ID构成了STUDENT表的列。 同样,COURSE_NAME和COURSE_ID构成COURSE表的列,依此类推。 -
主键表示的实体类型的键属性。在给定的ER图中,
COURSE_ID,STUDENT_ID,SUBJECT_ID和LECTURE_ID是实体的键属性。 -
多值属性由单独的表来表示。在
STUDENT表中,业余爱好是一个多值属性。 因此,无法在STUDENT表的单个列中表示多个值。 因此,需要创建另一个由STUDENT_ID和HOBBY属性组成的表STUD_HOBBY。 使用这两列,创建一个复合键。 -
派生属性表中未考虑。在
STUDENT表中,Age是派生属性。 它可以通过在任何时间点计算当前日期和出生日期之间的差值。
使用这些规则,可以将ER图转换为表和列,并分配表之间的映射。由给定ER图创建的表结构如下:
DBMS更高程度的关系
关系程度可以定义为一个实体中与另一个实体中的出现次数相关联的出现次数。
有三种程度的关系:
- 一对一(1 : 1)
- 一对多(1 : M)
- 多对多(M : N)
1. 一对一
在一对一关系中,实体的一次出现仅涉及另一实体中的一次出现。在实践中很少存在一对一的关系。
例如 :如果员工被分配公司汽车,那么该汽车只能由该员工驾驶。因此,员工和公司汽车就是一对一的关系。
2. 一对多
3. 多对多
关系模型概念
关系模型可以表示为包含列和行的表,每一行都称为元组。 列的每个表都有一个名称或属性。
域 - 包含属性可以采用的一组原子值。
属性 - 包含特定表中列的名称。每个属性必须有一个域。
关系实例 - 在关系数据库系统中,关系实例由一组有限的元组表示。关系实例没有重复的元组。
关系模式 - 关系模式包含所有列或属性的关系名称和名称。
关系键 - 在关系键中,每行都有一个或多个属性。它可以唯一地标识关系中的行。
示例- 学生关系
| NAME | ROLL_NO | PHONE_NO | ADDRESS | AGE |
|---|---|---|---|---|
| Maxsu | 14795 | 7305758992 | Noida | 24 |
| Shyam | 12839 | 9026288936 | Delhi | 35 |
| Laxman | 33289 | 8583287182 | Gurugram | 20 |
| Mahesh | 27857 | 7086819134 | Ghaziabad | 27 |
| Ganesh | 17282 | 9028 9i3988 | Delhi | 40 |
- 在上面表中,
NAME,ROLL_NO,PHONE_NO,ADDRESS和AGE都是属性。 - 模式
STUDENT的实例有5个元组。 - 第三行数据是 -
Laxman,33289,8583287182,Gurugram,20
关系的属性
- 关系的名称与所有其他关系不同。
- 每个关系单元格只包含一个原子(单个)值
- 每个属性都包含不同的名称
- 属性域没有意义
- 元组没有重复的值
- 元组的顺序可以有不同的顺序
DBMS关系代数
关系代数是一种过程查询语言,它提供了一步一步的过程来获取查询的结果。 它使用运算符来执行查询。
关系操作的类型
1. 选择操作
- 选择(select)操作选择满足给定谓词的元组。
- 它由西格玛(σ)表示。
符号: σ p(r)
其中:
σ用于选择预测r用于关系p用作命题逻辑公式,可以使用以下连接符:AND OR和NOT。这些关系可以用作关系运算符,如:=,≠,≥,<,>和≤。
例如 :LOAN关系
| BRANCH_NAME | LOAN_NO | AMOUNT |
|---|---|---|
| Downtown | L-17 | 1000 |
| Redwood | L-23 | 2000 |
| Perryride | L-15 | 1500 |
| Downtown | L-14 | 1500 |
| Mianus | L-13 | 500 |
| Roundhill | L-11 | 900 |
| Perryride | L-16 | 1300 |
输入:
σ BRANCH_NAME="perryride" (LOAN)
输出:
| BRANCH_NAME | LOAN_NO | AMOUNT |
|---|---|---|
| Perryride | L-15 | 1500 |
| Perryride | L-16 | 1300 |
2.项目操作
此操作显示希望在结果中显示的那些属性的列表。其余属性从表中消除。
它用Π表示。
符号 : ∏ A1, A2, An (r)
其中,
A1,A2,A3用作关系r的属性名称。
示例 : 客户关系
| NAME | STREET | CITY |
|---|---|---|
| Jones | Main | Harrison |
| Smith | North | Rye |
| Hays | Main | Harrison |
| Curry | North | Rye |
| Johnson | Alma | Brooklyn |
| Brooks | Senator | Brooklyn |
输入 -
∏ NAME, CITY (CUSTOMER)
| NAME | CITY |
|---|---|
| Jones | Harrison |
| Smith | Rye |
| Hays | Harrison |
| Curry | Rye |
| Johnson | Brooklyn |
| Brooks | Brooklyn |
3.联合操作
假设有两个元组R和S。并集操作包含R或S中的所有元组或R&S中的两个元组。
它消除了重复的元组。它使用∪表示。
符号 : R ∪ S
联合操作必须符合以下条件:
R和S必须具有相同数量的属性。- 自动消除重复的元组。
示例:存款人关系
| CUSTOMER_NAME | ACCOUNT_NO |
|---|---|
| Johnson | A-101 |
| Smith | A-121 |
| Mayes | A-321 |
| Turner | A-176 |
| Johnson | A-273 |
| Jones | A-472 |
| Lindsay | A-284 |
借款人关系
| CUSTOMER_NAME | LOAN_NO |
|---|---|
| Jones | L-17 |
| Smith | L-23 |
| Hayes | L-15 |
| Jackson | L-14 |
| Curry | L-93 |
| Smith | L-11 |
| Williams | L-17 |
输入:
∏ CUSTOMER_NAME (BORROW) ∪ ∏ CUSTOMER_NAME (DEPOSITOR)
输出 -
CUSTOMER_NAME ---------------------------------------- Johnson Smith Hayes Turner Jones Lindsay Jackson Curry Williams Mayes
4. 集合交集
假设有两个元组R和S,集合交集操作包含R&S中的所有元组。
它用交叉∩符号表示。
R ∩ S
示例:使用上面的存款人(DEPOSITOR)表和借款人(BORROW)表
输入:
∏ CUSTOMER_NAME (BORROW) ∩ ∏ CUSTOMER_NAME (DEPOSITOR)
输出:
CUSTOMER_NAME -------------------------------- Smith Jones
5. 集合差集
假设有两个元组R和S。集合交集操作包含R中但不在S中的所有元组。它由交叉减号(-)表示。
R - S
示例:使用上面的存款人(DEPOSITOR)表和借款人(BORROW)表
输入:
∏ CUSTOMER_NAME (BORROW) - ∏ CUSTOMER_NAME (DEPOSITOR)
输出结果:
CUSTOMER_NAME --------------------------- Jackson Hayes Willians Curry
6. 笛卡尔积
笛卡尔积用于将一个表中的每一行与另一个表中的每一行组合。 它也被称为交叉产生。
它用X表示。
E X D
示例:EMPLOYEE表
| EMP_ID | EMP_NAME | EMP_DEPT |
|---|---|---|
| 1 | Smith | A |
| 2 | Harry | C |
| 3 | John | B |
DEPARTMENT表
| DEPT_NO | DEPT_NAME |
|---|---|
| A | Marketing |
| B | Sales |
| C | Legal |
输入:
EMPLOYEE X DEPARTMENT
输出:
| EMP_ID | EMP_NAME | EMP_DEPT | DEPT_NO | DEPT_NAME |
|---|---|---|---|---|
| 1 | Smith | A | A | Marketing |
| 1 | Smith | A | B | Sales |
| 1 | Smith | A | C | Legal |
| 2 | Harry | C | A | Marketing |
| 2 | Harry | C | B | Sales |
| 2 | Harry | C | C | Legal |
| 3 | John | B | A | Marketing |
| 3 | John | B | B | Sales |
| 3 | John | B | C | Legal |
7. 重命名操作
重命名操作用于重命名输出关系,它由rho(ρ)表示。
示例: 使用重命名运算符将STUDENT关系重命名为STUDENT1。
ρ(STUDENT1, STUDENT)
DBMS连接操作
当且仅当满足给定的连接条件时,连接操作才组合来自不同关系的相关元组。 它用⋈符号来表示。
示例:
员工(EMPLOYEE)表 -
| EMP_CODE | EMP_NAME |
|---|---|
| 101 | Stephan |
| 102 | Jack |
| 103 | Harry |
薪水(SALARY)表 -
| EMP_CODE | SALARY |
|---|---|
| 101 | 50000 |
| 102 | 30000 |
| 103 | 25000 |
操作符号:
(EMPLOYEE ⋈ SALARY)
输出结果如下:
| EMP_CODE | EMP_NAME | SALARY |
|---|---|---|
| 101 | Stephan | 50000 |
| 102 | Jack | 30000 |
| 103 | Harry | 25000 |
连接操作的类型:
1.自然连接
自然连接是R和S中所有组合的元组集,它们的公共属性名称相等。它用符号⋈表示。
示例 :使用上面的EMPLOYEE表和SALARY表:
输入:
∏EMP_NAME, SALARY (EMPLOYEE ⋈ SALARY)
输出结果如下 -
| EMP_NAME | SALARY |
|---|---|
| Stephan | 50000 |
| Jack | 30000 |
| Harry | 25000 |
2. 外部连接
外连接操作是连接操作的扩展,它用于处理缺失的信息。
示例:
EMPLOYEE表的结构和数据如下 -
| EMP_NAME | STREET | CITY |
|---|---|---|
| Ram | Civil line | Mumbai |
| Shyam | Park street | Kolkata |
| Ravi | M.G. Street | Delhi |
| Hari | Nehru nagar | Hyderabad |
FACT_WORKERS表的结构和数据如下 -
| EMP_NAME | BRANCH | SALARY |
|---|---|---|
| Ram | Infosys | 10000 |
| Shyam | Wipro | 20000 |
| Kuber | HCL | 30000 |
| Hari | TCS | 50000 |
输入 -
(EMPLOYEE ⋈ FACT_WORKERS)
| EMP_NAME | STREET | CITY | BRANCH | SALARY |
|---|---|---|---|---|
| Ram | Civil line | Mumbai | Infosys | 10000 |
| Shyam | Park street | Kolkata | Wipro | 20000 |
| Hari | Nehru nagar | Hyderabad | TCS | 50000 |
外连接基本上有三种类型:
- 左外连接
- 右外连接
- 全外连接
A. 左外连接:
- 左外连接包含
R和S中所有组合的元组集,它们的公共属性名称相等。 - 在左外连接中,
R中的元组但在S中没有匹配的元组。 - 它用
⟕表示。
示例:使用上面的EMPLOYEE表和FACT_WORKERS表
输入 -
EMPLOYEE ⟕ FACT_WORKERS
输出 -
| EMP_NAME | STREET | CITY | BRANCH | SALARY |
|---|---|---|---|---|
| Ram | Civil line | Mumbai | Infosys | 10000 |
| Shyam | Park street | Kolkata | Wipro | 20000 |
| Hari | Nehru street | Hyderabad | TCS | 50000 |
| Ravi | M.G. Street | Delhi | NULL | NULL |
B. 右外连接:
- 右外连接包含
R和S中所有组合的元组集,它们的公共属性名称相等。 - 在右外连接中,
S中的元组在R中没有匹配的元组。 - 它使用
⟖表示。
输入 -
EMPLOYEE ⟖ FACT_WORKERS
输出 -
| EMP_NAME | BRANCH | SALARY | STREET | CITY |
|---|---|---|---|---|
| Ram | Infosys | 10000 | Civil line | Mumbai |
| Shyam | Wipro | 20000 | Park street | Kolkata |
| Hari | TCS | 50000 | Nehru street | Hyderabad |
| Kuber | HCL | 30000 | NULL | NULL |
C. 全外连接:
- 完全外连接类似于左连接或右连接,除了它包含来自两个表的所有行。
- 在完全外连接中,包含
R中的元组在S中没有匹配的元组,S中的元组在其公共属性名称中的R中没有匹配的元组。 - 它使用
⟗表示。
示例:使用上面的EMPLOYEE表和FACT_WORKERS表
输入 -
EMPLOYEE ⟗ FACT_WORKERS
输出 -
| EMP_NAME | STREET | CITY | BRANCH | SALARY |
|---|---|---|---|---|
| Ram | Civil line | Mumbai | Infosys | 10000 |
| Shyam | Park street | Kolkata | Wipro | 20000 |
| Hari | Nehru street | Hyderabad | TCS | 50000 |
| Ravi | M.G. Street | Delhi | NULL | NULL |
| Kuber | NULL | NULL | HCL | 30000 |
3. 相等连接
它也被称为内连接,这是最常见的加入。 它基于相等条件的匹配数据。相等连接使用比较运算符(=)。
示例:
CUSTOMER表 -
| CLASS_ID | NAME |
|---|---|
| 1 | John |
| 2 | Harry |
| 3 | Jackson |
PRODUCT表 -
| PRODUCT_ID | CITY |
|---|---|
| 1 | Delhi |
| 2 | Mumbai |
| 3 | Noida |
输入 -
CUSTOMER ⋈ PRODUCT
输出 -
| CLASS_ID | NAME | PRODUCT_ID | CITY |
|---|---|---|---|
| 1 | John | 1 | Delhi |
| 2 | Harry | 2 | Mumbai |
| 3 | Harry | 3 | Noida |
DBMS完整性约束
完整性约束是一组规则,它用于保持信息质量。
完整性约束确保必须以不影响数据完整性的方式执行数据插入,更新和其他过程。
因此,完整性约束用于防止对数据库的意外损坏。
1. 域限制
域约束可以定义为属性的有效值集的定义。
域的数据类型包括字符串,字符,整数,时间,日期,货币等。属性的值必须在相应的域中可用。
2. 实体完整性约束
实体完整性约束表明主键值不能为空(null)。
这是因为主键值用于标识关系中的各个行,如果主键具有空(null)值,则将无法识别这些行。
表除主键字段之外的属性可以包含空(null)值。
示例-
3. 参照完整性约束
在两个表之间指定参照完整性约束。
在参照完整性约束中,如果表1 中的外键引用表2 的主键,则表1 中的外键的每个值必须为空(null)或在表2 中可用。
4. 键限制(约束)
键是用于唯一地标识其实体集内的实体的实体集。
实体集可以有多个键,但其中一个键将是主键。 主键可以在关系表中包含任何null和唯一值。
示例:
DBMS关系演算
关系演算是一种非过程查询语言。 在非过程查询语言中,用户关心如何获得最终结果的细节。
关系演算告诉我们要做什么但从未解释过如何做。
关系演算的类型:
1. 元组关系演算(TRC)
指定元组关系演算以选择关系中的元组。 在TRC中,过滤变量使用关系的元组。
关系的结果可以有一个或多个元组。
符号
{T | P (T)} 或 {T | Condition (T)}
其中,
T是由此产生的元组P(T)是用于获取T的条件。
示例:
{ T.name | Author(T) AND T.article = 'database' }
输出 :此查询从AUTHOR关系中选择元组。 它返回一个带有'name'的元组,Author写了一篇关于'database'的文章。
TRC(元组关系演算)可以量化。 在TRC中,我们可以使用存在性(∃)和通用量词(∀)。
示例:
{ R| ∃T ∈ Authors(T.article='database' AND R.name=T.name)}
输出:此查询将产生与前一个查询相同的结果。
2. 域关系演算(DRC)
第二种关系形式称为域关系演算。 在域关系演算中,过滤变量使用属性域。
域关系演算使用与元组演算相同的运算符。 它使用逻辑连接词∧(和),∨(或)和┓(非)。
它使用存在性(∃)和通用量词(∀)来绑定变量。
符号 -
{ a1, a2, a3, ..., an | P (a1, a2, a3, ... ,an)}
其中,
a1,a2是属性。P代表由内部属性构建的公式。
示例:
{< article, page, subject > | ∈ yiibai ∧ subject = 'database'}
输出:此查询将从关系yiibai生成文章,页面和主题,其中主题是数据库。
DBMS函数依赖
DBMS函数依赖是两个属性之间存在的关系。它通常存在于表中的主键和非键属性之间。
X → Y
函数依赖的左侧被称为决定因素,生产的右侧被称为依赖。
例如:
假设有一个包含属性的员工表:Emp_Id,Emp_Name,Emp_Address。
这里Emp_Id属性是唯一地标识employee表的Emp_Name属性,因为如果知道Emp_Id,就可以知道与这个Emp_Id属性关联的员工姓名。
函数依赖可以写成:
Emp_Id → Emp_Name
因此可以说Emp_Name在函数上依赖于Emp_Id。
函数依赖的类型
1. 平凡函数依赖
- 如果
B是A的子集,则A→B具有平凡的函数依赖性。 - 以下依赖关系也很简单:
A→A,B→B
示例:
假设有一个包含两列 - Employee_Id和Employee_Name的表。{Employee_id,Employee_Name}→Employee_Id是一个简单的函数依赖,Employee_Id是{Employee_Id,Employee_Name}的子集。
此外,Employee_Id→Employee_Id和Employee_Name→Employee_Name也是平凡的依赖关系。
2. 非平凡的功能依赖
如果B不是A的子集,则A→B具有非平凡的函数依赖性。
当A交叉点B为NULL时,则A→B被称为完全非平凡。
示例:
ID → Name, Name → DOB
DBMS推理规则(IR)
阿姆斯特朗的公理是基本的推理规则。
阿姆斯特朗的公理用于结束关系数据库的函数依赖。
推理规则是一种断言。 它可以应用于一组FD(函数依赖)以导出其他FD(函数依赖)。
使用推理规则,可以从初始集中导出额外的函数依赖。
函数依赖有6种类型的推理规则:
1. 自反规则(IR1)
在反身规则中,如果Y是X的子集,则X确定Y。
如果 X ⊇ Y 那么 X → Y
示例
X = {a, b, c, d, e}
Y = {a, b, c}
2. 增强规则(IR2)
增强也称为部分依赖。在增强中,如果X确定Y,则XZ确定任何Z。
如果 X → Y 那么 XZ → YZ
示例
对于 R(ABCD), 如果 A → B 那么 AC → BC
3. 传递规则(IR3)
在传递规则中,如果X确定Y并且Y确定Z,那么X也必须确定Z。
如果 X → Y 并且 Y → Z ,那么 X → Z
4. 联合规则(IR4)
在联合规则中,如果X确定Y并且X确定Z,那么X也必须确定Y和Z。
如果 X → Y 并且 X → Z 那么 X → YZ
证明
第1步. X → Y (给定) 第2步. X → Z (给定) 第3步. X → XY (通过X增强在第1步上使用IR2,其中 XX = X) 第4步. XY → YZ (通过用Y增强在第2步上使用IR2) 第5步. X → YZ (在第3步和第4步上使用IR3)
5. 分解规则(IR5)
分解规则也称为项目规则。 这是联合规则的逆转。该规则表示,如果X确定Y和Z,则X确定Y,X分别确定Z。
如果 X → YZ 那么 X → Y 并且 X → Z
证明
第1步. X → YZ (给定) 第2步. YZ → Y (使用IR1规则) 第3步. X → Y (在第1步和第2步上使用IR3规则)
6. 伪传递规则(IR6)
在伪传递规则中,如果X确定Y并且YZ确定W,则XZ确定W。
如果 X → Y 并且 YZ → W 那么 XZ → W
证明
第1步. X → Y (给定) 第2步. WY → Z (给定) 第3步. WX → WY (通过参数W使用第1步,并使用 IR2 规则) 第4步. WX → Z (在第3步和第2步使用IR3规则)
DBMS规范化
规范化是在数据库中组织数据的过程。
规范化用于最小化关系或关系集的冗余。 它还用于消除插入,更新和删除异常等不良特性。
规范化将较大的表分成较小的表,并使用关系链接它们。
普通表单用于减少数据库表中的冗余。
范式的类型
有四种类型的范式:
| 范式 | 描述说明 |
|---|---|
| 1NF | 如果它包含原子值,则关系为第范式(1NF)。 |
| 2NF | 如果它在1NF中,则关系将在2NF中,并且所有非关键属性完全依赖于主键。 |
| 3NF | 如果它在2NF中,并且不存在转换依赖性,则关系将在3NF中。 |
| 4NF | 如果它是Boyce-Codd范式(BCNF) 并且没有多值依赖关系,那么关系将在4NF中。 |
| 5NF | 如果它在4NF中并且不包含任何连接依赖关系并且连接应该是无损的,则关系在5NF中。 |
1NF
如果它包含原子值,则关系为第一范式(1NF)。
它声明表的属性不能包含多个值,它必须只包含单值属性。
第一范式不允许多值属性,复合属性及其组合。
示例:由于属性EMP_PHONE是一个多值属性,所以关系EMPLOYEE不在1NF中。
EMPLOYEE表结构和数据 -
| EMP_ID | EMP_NAME | EMP_PHONE | EMP_STATE |
|---|---|---|---|
| 14 | John | 7272826385, 9064738238 | UP |
| 20 | Harry | 8574783832 | Bihar |
| 12 | Sam | 7390372389, 8589830302 | Punjab |
将EMPLOYEE表分解为1NF如下所示:
| EMP_ID | EMP_NAME | EMP_PHONE | EMP_STATE |
|---|---|---|---|
| 14 | John | 7272826385 | UP |
| 14 | John | 9064738238 | UP |
| 20 | Harry | 8574783832 | Bihar |
| 12 | Sam | 7390372389 | Punjab |
| 12 | Sam | 8589830302 | Punjab |
2NF
在第二范式(2NF)中,首先关系必须是1NF。
在第二范式(2NF)中,所有非关键属性都完全依赖于主键。
示例:假设学校存储教师和教授科目信息相关的数据。 在学校里,教师可以教授多个科目。
老师(TEACHER)表的结构和数据如下 -
| TEACHER_ID | SUBJECT | TEACHER_AGE |
|---|---|---|
| 25 | Chemistry | 30 |
| 25 | Biology | 30 |
| 47 | English | 35 |
| 83 | Math | 38 |
| 83 | Computer | 38 |
在给定的表中,非主要属性TEACHER_AGE依赖于TEACHER_ID(TEACHER_ID列有两个83的值,同样对应的TEACHER_AGE属性的值都是38),它是候选键的适当子集。 这就是它违反2NF规则的原因。
要将给定的表转换为2NF,我们将其分解为两个表:
TEACHER_DETAIL表的结构和数据如下 -
| TEACHER_ID | TEACHER_AGE |
|---|---|
| 25 | 30 |
| 47 | 35 |
| 83 | 38 |
TEACHER_SUBJECT表的结构和数据如下 -
| TEACHER_ID | SUBJECT |
|---|---|
| 25 | Chemistry |
| 25 | Biology |
| 47 | English |
| 83 | Math |
| 83 | Computer |
3NF
如果它在2NF 中,并且不包含任何传递性部分依赖性,则关系将在3NF 中。
3NF 用于减少数据重复,它还用于实现数据完整性。
如果非素数属性没有传递依赖关系,则关系必须是第三范式。
如果关系对于每个非平凡函数依赖关系X→Y保持至少以下条件之一,则该关系处于第三范式。
X是一把超级主键。Y是主键属性,即Y的每个元素是某个候选键的一部分。
示例:
EMPLOYEE_DETAIL表的结构和数据:
| EMP_ID | EMP_NAME | EMP_ZIP | EMP_STATE | EMP_CITY |
|---|---|---|---|---|
| 222 | Harry | 201010 | UP | Noida |
| 333 | Stephan | 02228 | US | Boston |
| 444 | Lan | 60007 | US | Chicago |
| 555 | Katharine | 06389 | UK | Norwich |
| 666 | John | 462007 | MP | Bhopal |
上述表(EMPLOYEE_DETAIL)中的超级键是:
{EMP_ID}, {EMP_ID, EMP_NAME}, {EMP_ID, EMP_NAME, EMP_ZIP}....等等
候选键:{EMP_ID}
非主属性:在给定表中,除EMP_ID之外的所有属性都是非主属性。
这里,EMP_STATE&EMP_CITY依赖于EMP_ZIP,而EMP_ZIP依赖于EMP_ID。 非主属性(EMP_STATE,EMP_CITY)可传递地依赖于超级主键(EMP_ID)。 它违反了第三范式的规则。
这就是为什么需要将EMP_CITY和EMP_STATE移动到新的表,并将EMP_ZIP作为主键。
员工(EMPLOYEE)表的结构和数据如下:
| EMP_ID | EMP_NAME | EMP_ZIP |
|---|---|---|
| 222 | Harry | 201010 |
| 333 | Stephan | 02228 |
| 444 | Lan | 60007 |
| 555 | Katharine | 06389 |
| 666 | John | 462007 |
员工邮编(EMPLOYEE_ZIP)表的结构和数据如下:
| EMP_ZIP | EMP_STATE | EMP_CITY |
|---|---|---|
| 201010 | UP | Noida |
| 02228 | US | Boston |
| 60007 | US | Chicago |
| 06389 | UK | Norwich |
| 462007 | MP | Bhopal |
4NF
如果它是Boyce Codd范式,并且没有多值依赖关系,那么关系将是4NF。
对于依赖性A→B,如果对于单个A值,存在多个B值,则该关系将是多值依赖性。
示例
STUDENT表结构和数据如下 -
| STU_ID | COURSE | HOBBY |
|---|---|---|
| 21 | Computer | Dancing |
| 21 | Math | Singing |
| 34 | Chemistry | Dancing |
| 74 | Biology | Cricket |
| 59 | Physics | Hockey |
上面给定的STUDENT表是符合3NF,但COURSE和HOBBY是两个独立的实体。因此,COURSE和HOBBY之间没有关系。
在学生关系中,一个学生的STU_ID是21,它有两门课程,计算机和数学以及两个爱好,舞蹈和歌唱。 因此,对STU_ID存在多值依赖性,这导致不必要的数据重复。
因此,要将上表转换为4NF,我们可以将其分解为两个表:
STUDENT_COURSE表的结构和数据 -
| STU_ID | COURSE |
|---|---|
| 21 | Computer |
| 21 | Math |
| 34 | Chemistry |
| 74 | Biology |
| 59 | Physics |
STUDENT_HOBBY表的结构和数据 -
| STU_ID | HOBBY |
|---|---|
| 21 | Dancing |
| 21 | Singing |
| 34 | Dancing |
| 74 | Cricket |
| 59 | Hockey |
5NF
如果它在4NF 中并且不包含任何连接依赖关系并且连接应该是无损的,则关系在5NF 中。
当所有表都被分成尽可能多的表以便避免冗余时,满足5NF 。
5NF 也称为项目连接正常形式(PJ/NF)。
示例-
| SUBJECT | LECTURER | SEMESTER |
|---|---|---|
| Computer | Anshika | Semester 1 |
| Computer | John | Semester 1 |
| Math | John | Semester 1 |
| Math | Akash | Semester 2 |
| Chemistry | Praveen | Semester 1 |
在上表中,John为第一学期提供计算机和数学课程,但他没有学习第二学期的数学课程。在这种情况下,需要组合所有这些字段来识别有效数据。
假设添加了一个新学期:第3学期,但不知道科目以及由哪个讲师来讲该科目,因此将讲师(Lecturer)和科目(Subject)留为NULL。 但是这三个列要组合在一起充当主键,因此不能将其他两列留空(NULL)。
因此,为了使上表成为5NF,可以将它分解为三个关系P1,P2和P3:
P1表 -
| SEMESTER | SUBJECT |
|---|---|
| Semester 1 | Computer |
| Semester 1 | Math |
| Semester 1 | Chemistry |
| Semester 2 | Math |
P2表 -
| SUBJECT | LECTURER |
|---|---|
| Computer | Anshika |
| Computer | John |
| Math | John |
| Math | Akash |
| Chemistry | Praveen |
P3表 -
| SEMSTER | LECTURER |
|---|---|
| Semester 1 | Anshika |
| Semester 1 | John |
| Semester 1 | John |
| Semester 2 | Akash |
| Semester 1 | Praveen |
DBMS第一范式(1NF)
如果它包含原子值,则关系为第一范式(1NF)。
它声明表的属性不能包含多个值,它必须只包含单值属性。
第一范式不允许多值属性,复合属性及其组合。
示例:由于属性EMP_PHONE是一个多值属性,所以关系EMPLOYEE不在1NF中。
EMPLOYEE表结构和数据 -
| EMP_ID | EMP_NAME | EMP_PHONE | EMP_STATE |
|---|---|---|---|
| 14 | John | 7272826385, 9064738238 | UP |
| 20 | Harry | 8574783832 | Bihar |
| 12 | Sam | 7390372389, 8589830302 | Punjab |
将EMPLOYEE表分解为1NF如下所示:
| EMP_ID | EMP_NAME | EMP_PHONE | EMP_STATE |
|---|---|---|---|
| 14 | John | 7272826385 | UP |
| 14 | John | 9064738238 | UP |
| 20 | Harry | 8574783832 | Bihar |
| 12 | Sam | 7390372389 | Punjab |
| 12 | Sam | 8589830302 | Punjab |
DBMS第二范式(2NF)
在第二范式(2NF)中,首先关系必须是1NF。
在第二范式(2NF)中,所有非关键属性都完全依赖于主键。
示例:假设学校存储教师和教授科目信息相关的数据。 在学校里,教师可以教授多个科目。
老师(TEACHER)表的结构和数据如下 -
| TEACHER_ID | SUBJECT | TEACHER_AGE |
|---|---|---|
| 25 | Chemistry | 30 |
| 25 | Biology | 30 |
| 47 | English | 35 |
| 83 | Math | 38 |
| 83 | Computer | 38 |
在给定的表中,非主要属性TEACHER_AGE依赖于TEACHER_ID(TEACHER_ID列有两个83的值,同样对应的TEACHER_AGE属性的值都是38),它是候选键的适当子集。 这就是它违反2NF规则的原因。
要将给定的表转换为2NF,我们将其分解为两个表:
TEACHER_DETAIL表的结构和数据如下 -
| TEACHER_ID | TEACHER_AGE |
|---|---|
| 25 | 30 |
| 47 | 35 |
| 83 | 38 |
TEACHER_SUBJECT表的结构和数据如下 -
| TEACHER_ID | SUBJECT |
|---|---|
| 25 | Chemistry |
| 25 | Biology |
| 47 | English |
| 83 | Math |
| 83 | Computer |
DBMS第三范式(3NF)
如果它在2NF 中,并且不包含任何传递性部分依赖性,则关系将在3NF 中。
3NF 用于减少数据重复,它还用于实现数据完整性。
如果非素数属性没有传递依赖关系,则关系必须是第三范式。
如果关系对于每个非平凡函数依赖关系X→Y保持至少以下条件之一,则该关系处于第三范式。
X是一把超级主键。Y是主键属性,即Y的每个元素是某个候选键的一部分。
示例:
EMPLOYEE_DETAIL表的结构和数据:
| EMP_ID | EMP_NAME | EMP_ZIP | EMP_STATE | EMP_CITY |
|---|---|---|---|---|
| 222 | Harry | 201010 | UP | Noida |
| 333 | Stephan | 02228 | US | Boston |
| 444 | Lan | 60007 | US | Chicago |
| 555 | Katharine | 06389 | UK | Norwich |
| 666 | John | 462007 | MP | Bhopal |
上述表(EMPLOYEE_DETAIL)中的超级键是:
{EMP_ID}, {EMP_ID, EMP_NAME}, {EMP_ID, EMP_NAME, EMP_ZIP}....等等
候选键:{EMP_ID}
非主属性:在给定表中,除EMP_ID之外的所有属性都是非主属性。
这里,EMP_STATE&EMP_CITY依赖于EMP_ZIP,而EMP_ZIP依赖于EMP_ID。 非主属性(EMP_STATE,EMP_CITY)可传递地依赖于超级主键(EMP_ID)。 它违反了第三范式的规则。
这就是为什么需要将EMP_CITY和EMP_STATE移动到新的表,并将EMP_ZIP作为主键。
员工(EMPLOYEE)表的结构和数据如下:
| EMP_ID | EMP_NAME | EMP_ZIP |
|---|---|---|
| 222 | Harry | 201010 |
| 333 | Stephan | 02228 |
| 444 | Lan | 60007 |
| 555 | Katharine | 06389 |
| 666 | John | 462007 |
员工邮编(EMPLOYEE_ZIP)表的结构和数据如下:
| EMP_ZIP | EMP_STATE | EMP_CITY |
|---|---|---|
| 201010 | UP | Noida |
| 02228 | US | Boston |
| 60007 | US | Chicago |
| 06389 | UK | Norwich |
| 462007 | MP | Bhopal |
DBMS第四范式(4NF)
如果它是Boyce Codd范式,并且没有多值依赖关系,那么关系将是4NF。
对于依赖性A→B,如果对于单个A值,存在多个B值,则该关系将是多值依赖性。
示例
STUDENT表结构和数据如下 -
| STU_ID | COURSE | HOBBY |
|---|---|---|
| 21 | Computer | Dancing |
| 21 | Math | Singing |
| 34 | Chemistry | Dancing |
| 74 | Biology | Cricket |
| 59 | Physics | Hockey |
上面给定的STUDENT表是符合3NF,但COURSE和HOBBY是两个独立的实体。因此,COURSE和HOBBY之间没有关系。
在学生关系中,一个学生的STU_ID是21,它有两门课程,计算机和数学以及两个爱好,舞蹈和歌唱。 因此,对STU_ID存在多值依赖性,这导致不必要的数据重复。
因此,要将上表转换为4NF,我们可以将其分解为两个表:
STUDENT_COURSE表的结构和数据 -
| STU_ID | COURSE |
|---|---|
| 21 | Computer |
| 21 | Math |
| 34 | Chemistry |
| 74 | Biology |
| 59 | Physics |
STUDENT_HOBBY表的结构和数据 -
| STU_ID | HOBBY |
|---|---|
| 21 | Dancing |
| 21 | Singing |
| 34 | Dancing |
| 74 | Cricket |
| 59 | Hockey |
DBMS第五范式(5NF)
如果它在4NF 中并且不包含任何连接依赖关系并且连接应该是无损的,则关系在5NF 中。
当所有表都被分成尽可能多的表以便避免冗余时,满足5NF 。
5NF 也称为项目连接正常形式(PJ/NF)。
示例-
| SUBJECT | LECTURER | SEMESTER |
|---|---|---|
| Computer | Anshika | Semester 1 |
| Computer | John | Semester 1 |
| Math | John | Semester 1 |
| Math | Akash | Semester 2 |
| Chemistry | Praveen | Semester 1 |
在上表中,John为第一学期提供计算机和数学课程,但他没有学习第二学期的数学课程。在这种情况下,需要组合所有这些字段来识别有效数据。
假设添加了一个新学期:第3学期,但不知道科目以及由哪个讲师来讲该科目,因此将讲师(Lecturer)和科目(Subject)留为NULL。 但是这三个列要组合在一起充当主键,因此不能将其他两列留空(NULL)。
因此,为了使上表成为5NF,可以将它分解为三个关系P1,P2和P3:
P1表 -
| SEMESTER | SUBJECT |
|---|---|
| Semester 1 | Computer |
| Semester 1 | Math |
| Semester 1 | Chemistry |
| Semester 2 | Math |
P2表 -
| SUBJECT | LECTURER |
|---|---|
| Computer | Anshika |
| Computer | John |
| Math | John |
| Math | Akash |
| Chemistry | Praveen |
P3表 -
| SEMSTER | LECTURER |
|---|---|
| Semester 1 | Anshika |
| Semester 1 | John |
| Semester 1 | John |
| Semester 2 | Akash |
| Semester 1 | Praveen |
DBMS关系分解
当关系模型中的关系不是适当的范式时,则需要分解关系。
在数据库中,它将表分成多个表。
如果关系没有适当的分解,则可能导致信息丢失等问题。
分解用于消除一些不良设计的问题,如异常,不一致和冗余。
分解的类型
1. 无损分解
- 如果信息没有从分解的关系中丢失,那么分解将是无损的。
- 无损分解保证了关系的连接将产生与分解时相同的关系。
- 如果所有分解的自然连接给出原始关系,则该关系被称为无损分解。
示例:
EMPLOYEE_DEPARTMENT表的结构和数据如下:
| EMP_ID | EMP_NAME | EMP_AGE | EMP_CITY | DEPT_ID | DEPT_NAME |
|---|---|---|---|---|---|
| 22 | Denim | 28 | Mumbai | 827 | Sales |
| 33 | Alina | 25 | Delhi | 438 | Marketing |
| 46 | Stephan | 30 | Bangalore | 869 | Finance |
| 52 | Katherine | 36 | Mumbai | 575 | Production |
| 60 | Jack | 40 | Noida | 678 | Testing |
将上述关系分解为两个关系表:EMPLOYEE和DEPARTMENT,它们分别如下:
EMPLOYEE表结构和数据如下 -
| EMP_ID | EMP_NAME | EMP_AGE | EMP_CITY |
|---|---|---|---|
| 22 | Denim | 28 | Mumbai |
| 33 | Alina | 25 | Delhi |
| 46 | Stephan | 30 | Bangalore |
| 52 | Katherine | 36 | Mumbai |
| 60 | Jack | 40 | Noida |
DEPARTMENT表结构和数据如下 -
| DEPT_ID | EMP_ID | DEPT_NAME |
|---|---|---|
| 827 | 22 | Sales |
| 438 | 33 | Marketing |
| 869 | 46 | Finance |
| 575 | 52 | Production |
| 678 | 60 | Testing |
现在,当这两个关系在公共列“EMP_ID”上连接时,结果关系将如下所示:
Employee ⋈ Department连接操作 -
| EMP_ID | EMP_NAME | EMP_AGE | EMP_CITY | DEPT_ID | DEPT_NAME |
|---|---|---|---|---|---|
| 22 | Denim | 28 | Mumbai | 827 | Sales |
| 33 | Alina | 25 | Delhi | 438 | Marketing |
| 46 | Stephan | 30 | Bangalore | 869 | Finance |
| 52 | Katherine | 36 | Mumbai | 575 | Production |
| 60 | Jack | 40 | Noida | 678 | Testing |
因此,分解是无损连接分解。
2. 依赖保留
- 它是数据库的一个重要约束。
- 在依赖项保留中,至少一个分解的表必须满足每个依赖项。
- 如果关系
R被分解为关系R1和R2,则R的依赖性必须是R1或R2的一部分,或者必须可以从R1和R2的函数依赖性的组合中导出。
例如,假设存在具有功能依赖性集(A -> BC)的关系R(A,B,C,D)。 关系R被分解为R1(ABC)和R2(AD),其是依赖性保持因为FD A-> BC是关系R1(ABC)的一部分。
DBMS多值依赖
- 当表中的两个属性彼此独立但两者都依赖于第三个属性时,会发生多值依赖性。
- 多值依赖包含至少两个依赖于第三个属性的属性,这就是它总是需要至少三个属性的原因。
示例:假设有一家自行车制造商公司每年生产两种颜色(白色和黑色)。
| BIKE_MODEL | MANUF_YEAR | COLOR |
|---|---|---|
| M2011 | 2008 | White |
| M2001 | 2008 | Black |
| M3001 | 2013 | White |
| M3001 | 2013 | Black |
| M4006 | 2017 | White |
| M4006 | 2017 | Black |
这里列COLOR和MANUF_YEAR依赖于BIKE_MODEL并且彼此独立。
在这种情况下,可以根据BIKE_MODEL将这两列调用为多值。 这些依赖关系的表示如下所示:
BIKE_MODEL → → MANUF_YEAR BIKE_MODEL → → COLOR
这可以理解为“BIKE_MODEL multidetermined MANUF_YEAR”和“BIKE_MODEL multidetermined COLOR”。
DBMS事务
- 当表中的两个属性彼此独立但两者都依赖于第三个属性时,会发生多值依赖性。
- 多值依赖包含至少两个依赖于第三个属性的属性,这就是它总是需要至少三个属性的原因。
示例:假设有一家自行车制造商公司每年生产两种颜色(白色和黑色)。
| BIKE_MODEL | MANUF_YEAR | COLOR |
|---|---|---|
| M2011 | 2008 | White |
| M2001 | 2008 | Black |
| M3001 | 2013 | White |
| M3001 | 2013 | Black |
| M4006 | 2017 | White |
| M4006 | 2017 | Black |
这里列COLOR和MANUF_YEAR依赖于BIKE_MODEL并且彼此独立。
在这种情况下,可以根据BIKE_MODEL将这两列调用为多值。 这些依赖关系的表示如下所示:
BIKE_MODEL → → MANUF_YEAR BIKE_MODEL → → COLOR
这可以理解为“BIKE_MODEL multidetermined MANUF_YEAR”和“BIKE_MODEL multidetermined COLOR”。
DBMS事务属性
事务具有四个属性,这些用于在事务之前和之后维护数据库的一致性。
事务属性
- 原子性(Atomicity)
- 一致性(Consistency)
- 隔离性(Isolation)
- 持久性(Durability)
1. 原子性
- 它声明事务的所有操作如有一个发生失败,则事务中止。
- 事务没有中途,即事务不能部分发生。 每个事务都被视为一个单元,并且运行完成或根本不执行。
原子性涉及以下两个操作:
中止: 如果事务中止,则所有更改都不可见。
提交: 如果事务提交,则所有更改都是可见的。
示例:假设事务T跟随T1和T2。假设A账户有600元,B由账户有300元。将账户A的100转账到账户B。
| T1 | T2 |
|---|---|
| Read(A),A:= A-100,Write(A) | Read(B),Y:= Y+100,Write(B) |
正常情况下事务完成后,账户A有500元,账户B有400元。
如果事务T在事务T1完成之后但在事务T2完成之前失败,则金额将从账户A中扣除但不会添加到账户B。这表示数据库状态不一致。为了确保数据库状态的正确性,必须完整地执行事务。
2. 一致性
- 保持完整性约束,以便数据库在事务之前和之后保持一致。
- 事务的执行将使数据库处于其先前稳定状态或新稳定状态。
- 数据库的一致属性声明每个事务都看到一致的数据库实例。
- 事务用于将数据库从一个一致状态转换为另一个一致状态。
例如:必须在交易之前或之后维持总金额。
T发生之前的总计 = 600+300=900 T发生之后的总计 = 500+400=900
因此,数据库是一致的。 在T1完成但T2失败的情况下,将发生不一致。
3. 隔离性
- 它表示,在第一个事务完成之前,第二个事务不能使用在执行事务时使用的数据。
- 在隔离中,如果正在执行事务
T1并使用数据项X,则在事务T1结束之前,任何其他事务T2都不能访问该数据项。 - DBMS的并发控制子系统强制执行隔离属性。
4. 持久性
- 持久性属性用于指示数据库的状态一致的情况,它声明事务发生了永久性变化。
- 它们不会因错误的事务错误操作或系统故障而丢失。 当事务完成时,数据库将达到称为一致状态的状态。 即使在系统出现故障的情况下,也不会丢失其一致状态。
- DBMS的恢复子系统负责隔离性属性。
DBMS事务的状态
在数据库中,事务可以处于以下状态之一 -
1. 活动状态
活动状态是每个事务的第一个状态。 在此状态下,正在执行事务。
例如: 在此处完成插入或删除或更新记录。 但是所有记录仍未保存到数据库中。
2. 部分提交
在部分提交状态下,事务执行其最终操作,但数据仍未保存到数据库中。
在总标记计算示例中,在该状态下执行总标记步骤的最终显示。
3. 提交
如果事务成功执行所有操作,则称该事务处于已提交状态。 在此状态下,所有效果现在都永久保存在数据库系统中。
4. 失败的状态
如果数据库恢复系统进行的任何检查失败,则该事务处于失败状态。
在总标记计算的示例中,如果数据库无法触发查询以获取标记,则事务将无法执行。
5. 中止
如果任何检查失败并且事务已达到失败状态,则数据库恢复系统将确保数据库处于之前的一致状态。 如果没有,那么它将中止或回滚事务以使数据库进入一致状态。
如果事务在事务中间失败,那么在执行事务之前,所有执行的事务都将回滚到其一致状态。
中止事务后,数据库恢复模块将选择以下两个操作之一:
- 重新开始事务
- 杀死事务
DBMS调度程序(Schedule)
从一个事务到另一个事务的一系列操作称为调度。 它用于保存每个单独事务中的操作顺序。
1. 串行调度
串行调度是一种调度,其中一个事务在开始另一个事务之前完全执行。 在串行调度中,当第一个事务完成其循环时,则执行下一个事务。
例如:假设有两个事务T1和T2有一些操作。 如果它没有交错操作,那么有以下两种可能的结果:
执行T1的所有操作,然后执行T2的所有操作。
- 在给定的(b)图中,调度A显示了序列调度,其中
T1之后跟T2。 - 在给定的(b)图中,附表B显示了序列调度,其中
T2后跟T1。
2. 非串行调度
如果允许交错操作,则将存在非串行调度。
它包含许多可能的顺序,系统可以在这些顺序中执行事务的各个操作。
在给定的图(c)和(d)中,附表C和附表D是非串行调度。 它具有交错操作。
这里,
调度A和调度B是串行调度。
调度C和调度D是非串行调度。
DBMS串行化的测试
从一个事务到另一个事务的一系列操作称为调度。 它用于保存每个单独事务中的操作顺序。
1. 串行调度
串行调度是一种调度,其中一个事务在开始另一个事务之前完全执行。 在串行调度中,当第一个事务完成其循环时,则执行下一个事务。
例如:假设有两个事务T1和T2有一些操作。 如果它没有交错操作,那么有以下两种可能的结果:
执行T1的所有操作,然后执行T2的所有操作。
- 在给定的(b)图中,调度A显示了序列调度,其中
T1之后跟T2。 - 在给定的(b)图中,附表B显示了序列调度,其中
T2后跟T1。
2. 非串行调度
如果允许交错操作,则将存在非串行调度。
它包含许多可能的顺序,系统可以在这些顺序中执行事务的各个操作。
在给定的图(c)和(d)中,附表C和附表D是非串行调度。 它具有交错操作。
这里,
调度A和调度B是串行调度。
调度C和调度D是非串行调度。
DBMS冲突串行化调度
如果不冲突的业务交换后,它可以转变成串行调度,调度被称为冲突串行化调度。
此调度将是一个序列化的冲突,如果它是相当于冲突的串行调度。
冲突操作
如果所有条件满足,则这两个操作会发生冲突:
- 两者都属于单独的事务。
- 它们具有相同的数据项。
- 它们至少包含一个写操作。
示例:
仅当S1和S2在逻辑上相等时才可以进行交换。
这里,S1 = S2。 这意味着它是非冲突的。
冲突等效
在冲突等效中,可以通过交换非冲突操作将其转换为另一个。 在给定的示例中,S2与S1相当冲突(S1可以通过交换非冲突操作转换为S2)。
当且仅当以下情况时,两个调度被认为是冲突等效的:
- 它们包含相同的事务集。
- 如果以相同的方式对每对冲突操作进行排序。
示例
调度S2是一个连续调度表,因为在这种情况下,T1的所有操作都是在开始任何T2操作之前执行的。通过交换S1的非冲突操作,可以将调度S1转换为连续时间表。
因为,S1是冲突可序列化的。
DBMS查看可序列化
如果视图相当于一个串行调度,那么视图将序列化。
如果调度是冲突可序列化的,那么它将是可序列化的。
可序列化的视图可序列化包含盲写。
查看等效
如果满足以下条件,则两个调度S1和调度S2被视为等效视图:
1. 初始读取
两个调度的初始读数必须相同。 假设有两个调度S1和S2。 在调度S1中,如果事务T1正在读取数据项A,则在S2中,事务T1也应该读取A。
以上两个调度表是等效视图,因为S1中的初始读操作由T1完成,而在S2中,它也由T1完成。
2. 更新读取
在调度S1中,如果Ti正在读取由Tj更新的A,那么在S2中,Ti也应该读取由Tj更新A。
以上两个调度表不是相同的,因为在S1中,T3读取A由T2更新,而在S2中,T3读取A由T1更新。
3. 最后写入
两个调度之间的最终写入必须相同。 在时间表S1中,如果事务T1最后更新A然后在S2中,则最终写入操作也应该由T1完成。
以上调度视图相等,因为S1中的最终写入操作由T3完成,而在S2中,最终写入操作也由T3完成。
示例:
有3个事务,可能的调度总数,如下所示:
= 3! = 6 S1 = <T1 T2 T3> S2 = <T1 T3 T2> S3 = <T2 T3 T1> S4 = <T2 T1 T3> S5 = <T3 T1 T2> S6 = <T3 T2 T1>
采取第一个调度S1:
调度S1
第1步: 对数据项进行最终更新
在调度S和S1中,除了初始读取之外没有读取,这是不需要检查该条件的原因。
第2步: 初始读取
S中的初始读操作由T1完成,在S1中,也由T1完成。
第3步: 最后写入
S中的最终写入操作由T3完成,在S1中,它也由T3完成。 因此,S和S1是等效视图。第一个调度S1满足所有三个条件,因此我们不需要检查另一个调度。
因此,查看等效的串行调度是:
T1 → T2 → T3
调度的可恢复性
有时,由于软件问题,系统崩溃或硬件故障,事务可能无法完全执行。 在这种情况下,失败的事务必须回滚。 但是其他一些事务也可能使用了失败的事务所产生的值。 所以我们也必须回滚那些事务。
上表1显示了具有两个事务的调度。 T1读取和写入A的值,该值由T2读取和写入。 T2提交但稍后,T1失败。 由于失败,必须回滚T1。 T2也应该回滚,因为它读取T1写入的值,但T2不能回滚,因为它已经提交。 因此,这种类型调度称为不可恢复调度。
不可恢复的调度:如果Tj读取Ti提交之前提交的Ti和Tj的更新值,则调度将是不可恢复的。
上表2显示了具有两个事务的调度。 事务T1读写A,该值由事务T2读写。 但后来,T1失败了。 因此,必须回滚T1。 T2应该回滚,因为T2已经读取了T1写入的值。 因为它在T1提交之前没有提交,所以也可以回滚事务T2。 所以它可以通过级联回滚来恢复。
可通过级联回滚恢复:如果Tj读取更新的Ti值,则可以使用级联回滚恢复调度。 Tj的提交被推迟到提交Ti。
上面的表3显示了具有两个事务的调度。 事务T1读取和写入A并提交,并且该值由T2读取和写入。 所以这是一个级联较少的可恢复调度。
DBMS故障分类
要找到问题发生的位置,我们将故障(失败)归纳为以下类别:
- 事务失败
- 系统崩溃
- 磁盘故障
1. 事务失败
当事务无法执行或者它到达无法继续执行的点时发生事务失败。 如果一些事务或进程受到损害,那么这称为事务失败。
事务失败的原因可能是 -
- 逻辑错误:如果由于某些代码错误或内部错误情况导致事务无法完成,则会发生逻辑错误。
- 语法错误:它发生在DBMS本身终止活动事务的位置,因为数据库系统无法执行它。 例如,如果出现死锁或资源不可用,系统将中止活动事务。
2. 系统崩溃
由于电源故障或其他硬件或软件故障,可能会发生系统故障。 示例:操作系统错误。
失败停止假设:在系统崩溃时,假定非易失性存储不会被破坏。
3.磁盘故障
- 它发生在硬盘驱动器或存储驱动器经常出现故障的地方。这是技术发展初期的常见问题。
- 磁盘故障是由于坏扇区的形成,磁盘磁盘崩溃以及磁盘无法访问或任何其他故障造成的,这些故障会破坏全部或部分磁盘存储。
DBMS基于日志的恢复
DBMS基于日志的恢复 -
- 日志是一系列记录。 每个事务的日志都保存在一些稳定的存储中,以便在发生任何故障时,可以从那里恢复。
- 如果对数据库执行任何操作,则它将记录在日志中。
- 但是,应该在数据库中应用实际事务之前完成存储日志的过程。
假设有一项事务,它执行修改学生所在的城市。 为此事务编写以下日志。
- 启动事务时,它会写入“启动”日志。
<Tn, Start>
- 当事务城市从“Haikou”修改为“Shanghai”时,则会将另一个日志写入该文件。
<Tn, City, 'Haikou', 'Shanghai' >
- 当事务完成时,它会写入另一个日志以指示事务结束。
<Tn, Commit>
修改数据库有两种方法:
1. 延期数据库修改:
- 如果事务在提交之前不修改数据库,则会发生延迟修改技术。
- 在此方法中,将创建所有日志并将其存储在稳定存储中,并在事务提交时更新数据库。
2. 立即修改数据库:
- 如果在事务仍处于活动状态时发生数据库修改,则会发生立即修改技术。
- 在这种技术中,每次操作后都会立即修改数据库。 它遵循实际的数据库修改。
使用日志记录恢复
当系统崩溃时,系统会查询日志以查找需要撤消的事务以及需要重做的事务。
- 如果日志包含记录
<Ti,Start>和<Ti,Commit>或<Ti,Commit>,则需要重做事务Ti。 - 如果日志包含记录
<Tn,Start>但不包含<Ti,commit>或<Ti,abort>的记录,则需要撤消事务Ti。
DBMS检查点
- 检查点(checkpoint)是一种机制,其中所有先前的日志都从系统中删除并永久存储在存储磁盘中。
- 检查点就像一个书签。 在执行事务时,标记此类检查点,然后使用事务的步骤执行事务,将创建日志文件。
- 当它到达检查点时,事务将更新到数据库中,直到那时,整个日志文件将从文件中删除。 然后使用新的事务步骤更新日志文件,直到下一个检查点,依此类推。
- 检查点用于声明DBMS处于一致状态之前的一个点,并且所有事务都已提交。
使用检查点恢复
通过以下方式,恢复系统从此故障中恢复数据库:
- 恢复系统从头开始读取日志文件。它将日志文件从T4读取到T1。
- 恢复系统维护两个列表,一个重做列表和一个撤销列表。
- 如果恢复系统看到日志
<Tn,Start>和<Tn,Commit>或仅<Tn,Commit>,则事务将进入重做状态。在重做列表及其上一个列表中,将删除所有事务,然后在保存日志之前重新执行。 - 例如: 在日志文件中,事务T2和T3将具有
<Tn,Start>和<Tn,Commit>。 T1事务在日志文件中只有<Tn,commit>。这就是在检查点超越后提交事务的原因。因此,它将T1,T2和T3事务置于重做列表中。 - 如果恢复系统看到带有
<Tn,Start>的日志但未找到提交或中止日志,则事务将进入撤消状态。在撤消列表中,撤消所有事务,并删除其日志。 - 例如: 事务T4将具有
<Tn,Start>。因此,T4将被置于撤销列表中,因为此事务尚未完成且失败。
DBMS死锁
死锁是两个或多个事务无限期地等待彼此放弃锁定的情况。 死锁被认为是DBMS中最令人恐惧的并发症之一,因为任务都没有完成,并且永远处于等待状态。
例如:在student表中,事务T1对某些行进行锁定,需要更新grade表中的某些行。 同时,事务T2在等级表中的某些行上保持锁定,并且需要更新事务T1持有的Student表中的行。
现在,出现了问题。事务T1正在等待T2释放其锁定,同样,事务T2正在等待T1释放其锁定。 所有活动都陷入停顿状态并保持停滞状态。 它将保持静止状态,直到DBMS检测到死锁并中止其中一个事务。
死锁避免
当数据库陷入死锁状态时,最好避免使用数据库而不是中止或重新启动数据库。 这是浪费时间和资源。
死锁避免机制用于预先检测任何死锁情况。 像“等待图”这样的方法用于检测死锁情况,但该方法仅适用于较小的数据库。 对于较大的数据库,可以使用死锁预防方法。
死锁检测
在数据库中,当事务无限期地等待获取锁时,DBMS应检测事务是否涉及死锁。 锁管理器维护等待图以检测数据库中的死锁循环。
等待图
- 这是用于死锁检测的合适方法。 在此方法中,将根据事务及其锁定创建图。 如果创建的图具有循环或闭环,则存在死锁。
- 对于等待其他人持有的某些数据的每个事务,系统维护等待图。 如果图中有任何循环,系统将继续检查图。
等待上述场景的图如下所示:
死锁预防
死锁防止方法适用于大型数据库。 如果以永远不会发生死锁的方式分配资源,则可以防止死锁。
数据库管理系统分析事务的操作是否可以创建死锁情况。 如果他们这样做,那么DBMS从不允许执行该事务。
等待模式
在此模式中,如果事务请求已由另一个事务保持冲突锁定的资源,则DBMS只检查两个事务的时间戳。 它允许旧事务等待资源可用于执行。
假设存在两个事务Ti和Tj,并且让TS(T)是任何事务T的时间戳。如果T2通过某个其他事务持有锁并且T1请求T2持有的资源,则DBMS执行以下操作:
- 检查
TS(Ti)<TS(Tj)- 如果Ti是较旧的事务并且Tj保留了一些资源,则允许Ti等待直到数据项可用于执行。这意味着如果较旧的事务正在等待由较年轻的事务锁定的资源,则允许较旧的事务等待资源直到它可用。 - 检查
TS(Ti)<TS(Tj)- 如果Ti是较旧的事务并且保留了一些资源并且如果Tj正在等待它,则Tj被杀死并且随后以随机延迟但具有相同时间戳重新启动。
创伤等待模式
- 在创伤等待方案中,如果较旧的事务请求由较新的事务持有的资源,则较旧的事务迫使较新的事务杀死该事务并释放该资源。 在分钟延迟之后,重新启动较新的事务但具有相同的时间戳。
- 如果旧事务持有较新事务请求的资源,则要求较新的事务等到较早发布它。
DBMS并发控制
在并发控制中,可以同时执行多个事务。
它可能会影响事务结果。保持这些事务的执行顺序非常重要。
并发控制的问题
并发事务以不受控制的方式执行时可能会出现几个问题。 以下是并发控制中的三个问题。
- 更新丢失
- 脏读
- 不可重复读取
1. 更新丢失
- 当访问相同数据库项的两个事务包含其操作时,某些数据库项的值不正确,则会发生丢失的更新问题。
- 如果两个事务T1和T2读取记录然后更新它,那么第二个更新将覆盖更新第一个记录的效果。
其中,
- 在时间t2,事务-X读取A的值。
- 在时间t3,Transaction-Y读取A的值。
- 在时间t4,Transactions-X基于在时间t2看到的值写入A的值。
- 在时间t5,Transactions-Y基于在时间t3看到的值写入A的值。
- 因此,在时间T5,Transaction-X的更新丢失,因为事务y覆盖它而不查看其当前值。
- 这种类型的问题称为丢失更新问题,因为此处丢失了一个事务所做的更新。
2. 脏读
- 在一个事务更新数据库的项目,然后由于某种原因事务失败的情况下发生脏读。 更新的数据库项在被更改回原始值之前由另一个事务访问。
- 事务T1更新由T2读取的记录。 如果T1中止,则T2现在具有从未形成稳定数据库的一部分的值。
示例:
其中
- 在时间t2,事务-Y写入A的值。
- 在时间t3,Transaction-X读取A的值。
- 在时间t4,Transactions-Y回滚。 因此,它将A的值更改回t1之前的值。
- 因此,Transaction-X现在包含一个永远不会成为稳定数据库一部分的值。
- 这种类型的问题称为脏读问题,因为一个事务读取尚未提交的脏值。
3. 不可重复读取问题
- 不一致的检索问题也称为不可重复读取。 当事务在一组数据上计算某些汇总函数而其他事务正在更新数据时,则会发生不一致的检索问题。
- 事务T1读取记录,然后进行一些其他处理,在此期间事务T2更新记录。 现在,当事务T1读取记录时,新值将与先前的值不一致。
示例:
假设有两个事务在三个账户上运作。
Transaction-X正在进行所有余额的总和,而Transaction-Y正在将账户1中的金额50转移到账户-3。
这里,transaction-X产生550的结果是不正确的。 如果在数据库中写入此生成的结果,则数据库将变为不一致状态,因为实际总和为600。
在这里,transaction-X看到了数据库的不一致状态。
并发控制协议
并发控制协议可确保并发事务的原子性,隔离性和可串行性。 并发控制协议可以分为三类:
- 基于锁定的协议
- 时间戳协议
- 基于验证的协议
DBMS基于锁的协议
在这种类型的协议中,任何事务在获取适当的锁之前都无法读取或写入数据。 锁有两种类型:
1.共享锁:
- 它也称为只读锁。 在共享锁中,数据项只能由事务读取。
- 它可以在事务之间共享,因为当事务持有锁时,它无法更新数据项上的数据。
2.独占锁:
- 在独占锁中,数据项既可以是读取,也可以是事务写入。
- 这种锁是独占的,在此锁中,多个事务不会同时修改相同的数据。
有四种类型的锁定协议可用:
1. 简单的锁定协议
这是在事务时锁定数据的最简单方法。简单的基于锁的协议允许所有事务在插入或删除或更新数据之前锁定数据。 它将在完成交易后解锁数据项。
2.预先声明锁定协议
- 预先声明锁定协议评估事务以列出它们需要锁定的所有数据项。
- 在开始执行事务之前,它会请求DBMS对所有这些数据项进行所有锁定。
- 如果授予所有锁定,则此协议允许事务开始。 当事务完成后,它会释放所有锁。
- 如果未授予所有锁定,则此协议允许事务回滚并等待,直到授予所有锁定。
3.两阶段锁定(2PL)
- 两阶段锁定协议将事务的执行阶段分为三个部分。
- 在第一部分中,当事务的执行开始时,它寻求对它所需的锁的许可。
- 在第二部分中,事务获取所有锁。 一旦事务发布第一个锁,第三个阶段就会启动。
- 在第三阶段,事务不能要求任何新锁。它只释放获得的锁。
2PL有两个阶段:
增长阶段: 在增长阶段,事务可以获取数据项的新锁,但是不能释放任何锁。
缩小阶段: 在缩小阶段,可以释放事务所持有的现有锁,但不能获取新锁。
在下面的示例中,如果允许锁定转换,则可能发生以下阶段:
- 在生长阶段允许升级锁(从S(a)到X(a))。
- 锁定降级(从X(a)到S(a))必须在缩小阶段完成。
示例
以下方式显示了解锁和锁定如何使用2-PL。
事务T1:
- 成长阶段:从步骤1-3开始
- 收缩阶段:从步骤5-7开始
- 锁定点:第3点
事务T2:
- 成长阶段:从步骤2-6开始
- 收缩阶段:从步骤8-9开始
- 锁定点:第6点
4. 严格阶段锁定(Strict-2PL)
- Strict-2PL的第一阶段类似于2PL。 在第一阶段,在获取所有锁之后,事务继续正常执行。
- 2PL和严格2PL之间的唯一区别是Strict-2PL在使用后不释放锁。
- Strict-2PL等待整个事务提交,然后一次释放所有锁。
- Strict-2PL协议没有锁定释放的缩小阶段。
它没有像2PL那样的级联中止。
DBMS时间戳顺序协议
DBMS时间戳顺序协议-
- 时间戳顺序协议用于根据事务的时间戳对事务进行排序。 事务顺序只不过是事务创建的升序。
- 旧事务的优先级高于它首先执行的原因。 要确定事务的时间戳,此协议使用系统时间或逻辑计数器。
- 基于锁的协议用于在执行时管理事务之间的冲突对之间的顺序。 但是,基于时间戳的协议会在创建事务后立即开始工作。
- 假设有两个事务T1和T2。 假设事务T1已经以007次进入系统并且事务T2已经以009次进入系统。 T1具有更高的优先级,因此它首先执行,因为它首先进入系统。
- 时间戳顺序协议还保持对数据的最后“读取”和“写入”操作的时间戳。
基本时间戳排序协议的工作原理如下:
-
每当事务Ti发出Read(X)操作时,请检查以下条件:
- 如果
W_TS(X)> TS(Ti)则拒绝该操作。 - 如果
W_TS(X)<= TS(Ti)则执行操作。 - 更新所有数据项的时间戳。
- 如果
-
每当事务Ti发出Write(X)操作时,请检查以下条件:
- 如果
TS(Ti)<R_TS(X)则操作被拒绝。 - 如果
TS(Ti)<W_TS(X)则拒绝操作并且回滚Ti,否则执行操作。
其中, TS(TI)表示事务Ti的时间戳。R_TS(X)表示数据项X的读时间戳。W_TS(X)表示数据项X的写时间戳。
- 如果
TO协议的优点和缺点:
- TO协议确保可串行化,因为优先级图如下:
- TS协议确保免于死锁,这意味着没有事务等待。
- 但是时间表可能无法恢复,甚至可能无法级联。
DBMS基于验证的协议
验证阶段也称为乐观并发控制技术。 在基于验证的协议中,事务在以下三个阶段中执行:
- 读阶段 :在此阶段,读取并执行事务T。它用于读取各种数据项的值并将它们存储在临时局部变量中。 它可以对临时变量执行所有写操作,而无需更新实际数据库。
- 验证阶段 :在此阶段,将根据实际数据验证临时变量值,以查看它是否违反了可串行性。
- 写入阶段 :如果验证了事务的验证,则将临时结果写入数据库或系统,否则将回滚事务。
这里每个阶段都有以下不同的时间戳:
开始(Ti):它包含Ti开始执行的时间。
验证(Ti):它包含Ti完成其读取阶段并开始其验证阶段的时间。
完成(Ti):它包含Ti完成写入阶段的时间。
- 此协议用于使用验证阶段的时间戳确定事务序列化的时间戳,因为它是确定事务是提交还是回滚的实际阶段。
- 因此TS(T)= 验证(T)。
- 可验证性在验证过程中确定,它不能提前决定。
- 在执行事务时,它确保更大程度的并发性以及更少的冲突。
- 因此,它包含具有较少回滚次数的事务。
托马斯写入规则
托马斯(Thomas)写入规则为协议提供了可序列化顺序的保证。 它改进了基本时间戳排序算法。
基本的托马斯写规则如下:
- 如果
TS(T)< R_TS(X),则事务T被中止并回滚,并且操作被拒绝。
如果TS(T)< W_TS(X)则不执行事务的W_item(X)操作并继续处理。
如果条件1和条件2都不发生,则允许通过事务Ti执行WRITE操作并将W_TS(X)设置为TS(T)。
如果使用托马斯写规则,那么可以允许一些可序列化的时间表,如同给定图中的时间表所示,不会发生序列化冲突:
图:不可冲突序列化的可序列化调度
在上图中,T1读取并在T1写入相同数据项之前。此调度不会与可序列化冲突。
DBMS多重粒度
本节将从理解粒度的含义开始学习。
粒度: 它是允许锁定的数据项的大小。
多粒度
- 它可以定义为将数据库分层分解为可以锁定的块。
- 多粒度协议增强了并发性并减少了锁定开销。
- 它保留了锁定内容和锁定方式的轨迹。
- 可以轻松决定锁定数据项还是解锁数据项。这种类型的层次结构可以图形方式表示为树。
示例:考虑一个具有四级节点的树。
- 第一级或更高级别显示整个数据库。
- 第二级表示类型区域的节点。 更高级别的数据库恰好包含这些区域。
- 该区域由子节点组成,称为文件。 没有文件可以存在于多个区域中。
- 最后,每个文件都包含称为记录的子节点。 该文件恰好具有作为其子节点的记录。 没有记录代表多个文件。
-
因此,从顶层开始的树的级别如下:
- 数据库
- 区域
- 文件
- 记录
在此示例中,最高级别显示整个数据库。以下级别是文件,记录和字段。
有三种额外的锁定模式,具有多种粒度:
意图模式锁定
意图共享(IS) :它包含树的较低级别的显式锁定,但仅包含共享锁。
意图独占(IX) :它含有在与排他或共享锁较低水平显式锁定。
共享和意向独占(SIX) :在此锁定中,节点以共享模式锁定,并且某个节点由同一事务锁定在独占模式。
兼容性矩阵与意图锁定模式 :下表描述了这些锁定模式的兼容性矩阵:
它使用意图锁定模式来确保可串行化。它要求如果事务试图锁定节点,那么该节点必须遵循以下协议:
- 事务T1应遵循锁兼容性矩阵。
- 事务T1首先锁定树的根,它可以在任何模式下锁定它。
- 如果T1当前将节点的父节点锁定在IX或IS模式中,则事务T1将仅以S或IS模式锁定节点。
- 如果T1当前将节点的父节点锁定在IX或SIX模式中,则事务T1将仅以X,SIX或IX模式锁定节点。
- 如果T1之前没有解锁任何节点,则事务T1可以锁定节点。
- 如果T1当前没有节点锁定的子节点,则事务T1将解锁节点。
注意,在多粒度中,锁是以自上而下的顺序获取的,并且锁必须以自下而上的顺序释放。
- 如果事务T1在文件Fa中读取记录Ra9,则事务T1需要在IX模式下锁定数据库,区域A1和文件Fa。 最后,它需要在S模式下锁定Ra2。
- 如果事务T2修改文件Fa中的记录Ra9,那么它可以在IX模式下锁定数据库,区域A1和文件Fa之后执行此操作。 最后,它需要在X模式下锁定Ra9。
- 如果事务T3读取文件Fa中的所有记录,则事务T3需要锁定数据库,并且区域A需要在IS模式下。 - 最后,它需要在S模式下锁定Fa。
- 如果事务T4读取整个数据库,则T4需要以S模式锁定数据库。
DBMS文件组织
文件组织-
- 文件是记录的集合。使用主键,可以访问记录。访问的类型和频率可以由用于给定记录集的文件组织类型确定。
- 文件组织是各种记录之间的逻辑关系。此方法定义文件记录如何映射到磁盘块。
- 文件组织用于描述以块的形式存储记录的方式,并且块被放置在存储介质上。
- 将数据库映射到文件的第一种方法是使用多个文件并在任何给定文件中仅存储一个固定长度的记录。 另一种方法是构造我们的文件,以便可以包含多个记录长度。
- 固定长度记录的文件比可变长度记录的文件更容易实现。
文件组织的目标
- 它包含最佳记录选择,即可以尽可能快地选择记录。
- 要执行插入,删除或更新记录上的事务应该快速而简单。
- 由于插入,更新或删除,无法引发重复记录。
- 为了最小的存储成本,应该有效地存储记录。
文件组织类型
文件组织包含各种方法。 这些特定方法在访问或选择的利弊。 在文件组织中,程序员根据他的要求决定最适合的文件组织方法。
文件组织的类型如下:
- 顺序文件组织
- 堆文件组织
- 哈希文件组织
- B+文件组织
- 索引顺序访问方法(ISAM)
- 群集文件组织
顺序文件组织
此方法是文件组织的最简单方法。 在此方法中,文件按顺序存储。 这种方法可以通过两种方式实现:
1.堆文件方法
- 这是一种非常简单的方法。 在这种方法中,将记录按顺序存储,即一个接一个地存储。 这里,记录将按照它们插入表中的顺序插入。
- 在更新或删除任何记录的情况下,将在存储器块中搜索记录。 找到后,它将被标记为删除,并插入新记录。
插入新记录
假设有四个记录R1,R3,依此类推,直到R9和R8为序列。 因此,记录表示表中的一行。 假设要在序列中插入新记录R2,然后将它放在文件的末尾。 在这里,记录是任何表格中的一行。
2. 排序文件方法
- 在此方法中,新记录始终插入文件的末尾,然后它将按升序或降序对序列进行排序。 记录的排序基于任何主键或任何其他键。
- 在修改任何记录的情况下,它将更新记录然后对文件进行排序,最后,更新的记录放在正确的位置。
插入新记录
假设存在预先存在的四个记录R1,R3等的排序序列,直到R6和R7。 假设必须在序列中插入新记录R2,然后将其插入文件的末尾,然后它将对序列进行排序。
顺序文件组织的优点
- 它包含一种快速有效的方法来处理大量数据。
- 在这种方法中,文件可以很容易地存储在比磁带更便宜的存储机制中。
- 它设计简单。它不需要做太多工作来存储数据。
- 当必须访问大多数记录时,例如学生的成绩计算,生成工资单等,使用此方法。
- 此方法用于报告生成或统计计算。
顺序文件组织的缺点
- 它会比较浪费时间,因为无法跳过所需的特定记录,但必须按顺序移动,这需要更多的时间。
- 排序文件方法需要更多时间和空间来对记录进行排序。
堆文件组织
- 它是最简单,最基本的组织类型。它适用于数据块。在堆文件组织中,记录将插入文件的末尾。插入记录时,不需要对记录进行排序和排序。
- 当数据块已满时,新记录将存储在其他块中。这个新数据块不必是下一个数据块,但它可以选择存储器中的任何数据块来存储新记录。堆文件也称为无序文件。
- 在文件中,每个记录都有一个唯一的ID,文件中的每个页面都具有相同的大小。 DBMS负责存储和管理新记录。
插入新记录
假设在堆中有五个记录R1,R3,R6,R4和R5,并假设要在堆中插入新记录R2。 如果数据块3已满,则它将被插入DBMS选择的任何数据库中,假设是插入到数据块1,那么操作如下图所示:
如果想要搜索,更新或删除堆文件组织中的数据,那么需要遍历文件,直到获得所请求的记录。
如果数据库非常大,那么搜索,更新或删除记录将非常耗时,因为没有记录的排序或排序。 在堆文件组织中,需要检查所有数据,直到获得请求的记录。
堆文件组织的优点
- 这是一种非常好的批量插入文件组织方法。 如果有大量数据需要一次加载到数据库中,则此方法最适合。
- 在小型数据库的情况下,获取和检索记录比顺序记录更快。
堆文件组织的缺点
- 对于大型数据库,此方法效率低,因为搜索或修改记录需要时间。
哈希文件组织
哈希(散列)文件组织在记录的某些字段上使用哈希函数的计算。哈希函数的输出确定要放置记录的磁盘块的位置。
当必须使用哈希键列接收记录时,则生成地址,并使用该地址检索整个记录。 以同样的方式,当必须插入新记录时,使用哈希键生成地址并直接插入记录。 在删除和更新的情况下应用相同的过程。
在这种方法中,没有必要搜索和排序整个文件。 因为在此方法中,每条记录将随机存储在内存中。
B+文件组织
- B+树文件组织是索引顺序访问方法的高级方法,它使用树状结构在文件中存储记录。
- 它使用与
键-索引概念相同,其中主键用于对记录进行排序。 对于每个主键,将生成索引的值并与记录一起映射。 - B+树类似于二叉搜索树(BST),但它可以有两个以上的子节点。 在此方法中,所有记录仅存储在叶节点处,中间节点充当指向叶节点的指针,它们不包含任何记录。
上面B+树的描述:
- 树有一个根节点,即25。
- 存在具有节点的中间层。它们不存储实际记录。 它们只有指向叶节点的指针。
- 根节点左侧的节点包含根的先前值,右侧的节点包含根的下一个值,即分别为15和30。
- 只有一个叶节点只有值,即
10,12,17,20,24,27和29。 - 所有叶节点都是平衡的,因此搜索任何记录都更容易。
- 在此方法中,可以通过单个路径遍历搜索任何记录并轻松访问。
B+树文件组织的优点-
- 在这种文件组织方法中,搜索变得非常容易,因为所有记录仅存储在叶节点中并对顺序链表进行排序。
- 遍历树结构更容易,更快捷。
- B+树 的大小没有限制,因此记录数量可以增加或减少,B+树结构也可以增长或缩小。
- 它是一种平衡的树结构,任何插入/更新/删除都不会影响树的性能。
B+树文件组织的缺点
- 对于静态方法,此方法效率低下。
索引顺序访问方法(ISAM)
如果必须根据其索引值检索任何记录,则获取数据块的地址并从存储器中检索记录。
ISAM的优点:
- 在这种方法中,每条记录都有其数据块的地址,在庞大的数据库中搜索记录既快捷又简单。
- 此方法支持范围检索和记录的部分检索。 由于索引基于主键值,因此我们可以检索给定值范围的数据。 以相同的方式,也可以容易地搜索部分值,即,可以容易地搜索以“Max”开头的学生姓名。
ISAM的缺点
- 此方法需要磁盘中的额外空间来存储索引值。
- 插入新记录时,必须重建这些文件以维护序列。
- 删除记录后,需要释放它所使用的空间。 否则,数据库的性能将会降低。
群集文件组织
- 当两个或多个记录存储在同一文件中时,它称为群集。 这些文件在同一数据块中有两个或多个表,并且用于将这些表映射到一起的键属性仅存储一次。
- 该方法降低了在不同文件中搜索各种记录的成本。
- 当经常需要以相同条件连接表时,将使用群集文件组织。这些连接只会从两个表中提供几条记录。 在给定的示例中,仅检索指定部门的记录。此方法不能用于检索整个部门的记录。
在这种方法中,可以直接插入,更新或删除任何记录。 数据根据进行搜索键进行排序。 群集键是一种用于执行表连接的键。
集群文件组织有两种类型:
1. 索引集群
在索引集群中,记录基于集群键进行分组并一起存储。上述EMPLOYEE和DEPARTMENT关系是索引集群的示例。 此处,所有记录都根据群集键DEP_ID进行分组,并且所有记录都已分组。
2. 散列集群
它类似于索引集群。在散列集群中,不是基于集群键存储记录,而是生成集群键的散列键值,并使用相同的散列键值存储记录。
集群文件组织的优点
- 当频繁请求加入具有相同连接条件的表时,将使用群集文件组织。
- 当表之间存在
1 :M映射时,它提供了有效的结果。
集群文件组织的缺点
- 此方法对于非常大的数据库具有低性能。
- 如果连接条件有任何变化,则此方法无法使用。 如果改变加入条件,那么遍历文件需要花费很多时间。
- 此方法不适用于具有
1 :1条件的表。
DBMS顺序文件组织
此方法是文件组织的最简单方法。 在此方法中,文件按顺序存储。 这种方法可以通过两种方式实现:
1.堆文件方法
- 这是一种非常简单的方法。 在这种方法中,将记录按顺序存储,即一个接一个地存储。 这里,记录将按照它们插入表中的顺序插入。
- 在更新或删除任何记录的情况下,将在存储器块中搜索记录。 找到后,它将被标记为删除,并插入新记录。
插入新记录
假设有四个记录R1,R3,依此类推,直到R9和R8为序列。 因此,记录表示表中的一行。 假设要在序列中插入新记录R2,然后将它放在文件的末尾。 在这里,记录是任何表格中的一行。
2. 排序文件方法
- 在此方法中,新记录始终插入文件的末尾,然后它将按升序或降序对序列进行排序。 记录的排序基于任何主键或任何其他键。
- 在修改任何记录的情况下,它将更新记录然后对文件进行排序,最后,更新的记录放在正确的位置。
插入新记录
假设存在预先存在的四个记录R1,R3等的排序序列,直到R6和R7。 假设必须在序列中插入新记录R2,然后将其插入文件的末尾,然后它将对序列进行排序。
顺序文件组织的优点
- 它包含一种快速有效的方法来处理大量数据。
- 在这种方法中,文件可以很容易地存储在比磁带更便宜的存储机制中。
- 它设计简单。它不需要做太多工作来存储数据。
- 当必须访问大多数记录时,例如学生的成绩计算,生成工资单等,使用此方法。
- 此方法用于报告生成或统计计算。
顺序文件组织的缺点
- 它会比较浪费时间,因为无法跳过所需的特定记录,但必须按顺序移动,这需要更多的时间。
- 排序文件方法需要更多时间和空间来对记录进行排序。
DBMS堆文件组织
- 它是最简单,最基本的组织类型。它适用于数据块。在堆文件组织中,记录将插入文件的末尾。插入记录时,不需要对记录进行排序和排序。
- 当数据块已满时,新记录将存储在其他块中。这个新数据块不必是下一个数据块,但它可以选择存储器中的任何数据块来存储新记录。堆文件也称为无序文件。
- 在文件中,每个记录都有一个唯一的ID,文件中的每个页面都具有相同的大小。 DBMS负责存储和管理新记录。
插入新记录
假设在堆中有五个记录R1,R3,R6,R4和R5,并假设要在堆中插入新记录R2。 如果数据块3已满,则它将被插入DBMS选择的任何数据库中,假设是插入到数据块1,那么操作如下图所示:
如果想要搜索,更新或删除堆文件组织中的数据,那么需要遍历文件,直到获得所请求的记录。
如果数据库非常大,那么搜索,更新或删除记录将非常耗时,因为没有记录的排序或排序。 在堆文件组织中,需要检查所有数据,直到获得请求的记录。
堆文件组织的优点
- 这是一种非常好的批量插入文件组织方法。 如果有大量数据需要一次加载到数据库中,则此方法最适合。
- 在小型数据库的情况下,获取和检索记录比顺序记录更快。
堆文件组织的缺点
- 对于大型数据库,此方法效率低,因为搜索或修改记录需要时间。
DBMS哈希文件组织
哈希(散列)文件组织在记录的某些字段上使用哈希函数的计算。哈希函数的输出确定要放置记录的磁盘块的位置。
当必须使用哈希键列接收记录时,则生成地址,并使用该地址检索整个记录。 以同样的方式,当必须插入新记录时,使用哈希键生成地址并直接插入记录。 在删除和更新的情况下应用相同的过程。
在这种方法中,没有必要搜索和排序整个文件。 因为在此方法中,每条记录将随机存储在内存中。
DBMS B+树文件组织
哈希(散列)文件组织在记录的某些字段上使用哈希函数的计算。哈希函数的输出确定要放置记录的磁盘块的位置。
当必须使用哈希键列接收记录时,则生成地址,并使用该地址检索整个记录。 以同样的方式,当必须插入新记录时,使用哈希键生成地址并直接插入记录。 在删除和更新的情况下应用相同的过程。
在这种方法中,没有必要搜索和排序整个文件。 因为在此方法中,每条记录将随机存储在内存中。
DBMS索引顺序访问方法(ISAM)
如果必须根据其索引值检索任何记录,则获取数据块的地址并从存储器中检索记录。
ISAM的优点:
- 在这种方法中,每条记录都有其数据块的地址,在庞大的数据库中搜索记录既快捷又简单。
- 此方法支持范围检索和记录的部分检索。 由于索引基于主键值,因此我们可以检索给定值范围的数据。 以相同的方式,也可以容易地搜索部分值,即,可以容易地搜索以“Max”开头的学生姓名。
ISAM的缺点
- 此方法需要磁盘中的额外空间来存储索引值。
- 插入新记录时,必须重建这些文件以维护序列。
- 删除记录后,需要释放它所使用的空间。 否则,数据库的性能将会降低。
DBMS群集文件组织
- 当两个或多个记录存储在同一文件中时,它称为群集。 这些文件在同一数据块中有两个或多个表,并且用于将这些表映射到一起的键属性仅存储一次。
- 该方法降低了在不同文件中搜索各种记录的成本。
- 当经常需要以相同条件连接表时,将使用群集文件组织。这些连接只会从两个表中提供几条记录。 在给定的示例中,仅检索指定部门的记录。此方法不能用于检索整个部门的记录。
在这种方法中,可以直接插入,更新或删除任何记录。 数据根据进行搜索键进行排序。 群集键是一种用于执行表连接的键。
集群文件组织有两种类型:
1. 索引集群
在索引集群中,记录基于集群键进行分组并一起存储。上述EMPLOYEE和DEPARTMENT关系是索引集群的示例。 此处,所有记录都根据群集键DEP_ID进行分组,并且所有记录都已分组。
2. 散列集群
它类似于索引集群。在散列集群中,不是基于集群键存储记录,而是生成集群键的散列键值,并使用相同的散列键值存储记录。
集群文件组织的优点
- 当频繁请求加入具有相同连接条件的表时,将使用群集文件组织。
- 当表之间存在
1 :M映射时,它提供了有效的结果。
集群文件组织的缺点
- 此方法对于非常大的数据库具有低性能。
- 如果连接条件有任何变化,则此方法无法使用。 如果改变加入条件,那么遍历文件需要花费很多时间。
- 此方法不适用于具有
1 :1条件的表。
DBMS索引
在DBMS中索引 -
- 索引用于通过最小化处理查询时所需的磁盘访问次数来优化数据库的性能。
- 索引是一种数据结构。它用于快速定位和访问数据库表中的数据。
索引结构
- 数据库的第一列是搜索键,它包含表的主键或候选键的副本。主键的值按排序顺序存储,以便可以轻松访问相应的数据。
- 数据库的第二列是数据引用。 它包含一组指针,用于保存磁盘块的地址,可以在其中找到特定键的值。
索引方法
有序索引
通常对索引进行排序以使搜索更快,排序索引称为有序索引。
示例: 假设有一个包含几千条记录的employee表,每条记录的长度为10个字节。 如果它们的ID是以1,2,3 ......等开头,那么如果要使用ID为543来搜索学生的信息。
- 对于没有索引的数据库,需要从磁盘块开始搜索直到
543。 DBMS将在读取543 * 10 = 5430字节后读取记录。 - 在索引的情况下,直接使用索引进行搜索,DBMS将在读取
542 * 2 = 1084字节后读取记录,这与前一种情况相比非常少。
主键
- 如果索引是基于表的主键创建的,那么它被称为主索引。 这些主键对于每个记录都是唯一的,并且在记录之间包含
1:1的关系。 - 由于主键按排序顺序存储,因此搜索操作的性能非常高效。
- 主索引可以分为两种类型:密集索引和稀疏索引。
密集索引
- 密集索引包含数据文件中每个搜索键值的索引记录,它使搜索更快。
- 在此,索引表中的记录数与主表中的记录数相同。
- 它需要更多的空间来存储索引记录本身。索引记录具有搜索键和指向磁盘上实际记录的指针。
稀疏索引
在数据文件中,索引记录仅针对少数项目出现。 每个项目都指向一个区块。
在此,索引不是指向主表中的每个记录,而是指向间隙中主表中的记录。
聚类索引
- 聚簇索引可以定义为有序数据文件。 有时,索引是在非主键列上创建的,对于每个记录可能不是唯一的。
- 在这种情况下,为了更快地识别记录,将对两列或更多列进行分组以获取唯一值并从中创建索引。此方法称为聚类索引。
- 对具有相似特征的记录进行分组,并为这些组创建索引。
示例:假设公司在每个部门中包含多个员工。假设使用聚簇索引,其中属于同一Dept_ID的所有员工都被视为在单个集群中,并且索引指针指向整个集群。 这里Dept_ID是一个非唯一键。
二级索引
在稀疏索引中,随着表的大小增加,映射的大小也会增加。 这些映射通常保存在主存储器中,因此地址获取应该更快。 然后,辅助存储器根据从映射获得的地址搜索实际数据。 如果映射大小增加,那么获取地址本身会变慢。 在这种情况下,稀疏索引效率不高。 为了克服这个问题,引入了二级索引。
在二级索引中,为了减小映射的大小,引入了另一级索引。 在该方法中,最初选择列的巨大范围,使得第一级映射变小。 然后将每个范围进一步划分为更小的范围。 第一级的映射存储在主存储器中,因此地址获取更快。 第二级和实际数据的映射存储在辅助存储器(硬盘)中。
示例:
- 如果要在图中找到卷
111的记录,则它将搜索第一级索引中小于或等于111的最高条目。 这个级别将达到100。 - 然后在二级索引级别,它再次执行
max(111)<= 111并获得110。现在使用地址是:110,它进入数据块并开始搜索每个记录,直到它达到111。 - 这是在此方法中执行搜索的方式。插入,更新或删除也以相同的方式完成。
DBMS B+树
B+树是一个平衡的二叉搜索树,它遵循多级索引格式。
- 在B+树中,叶节点表示实际的数据指针,B+树确保所有叶节点保持在相同的高度。
- 在B+树中,叶节点使用链表链接,因此,B+树可以支持随机访问以及顺序访问。
B+树的结构
在B+树中,每个叶节点与根节点的距离相等。B+树的顺序为n,其中n对于每个B+树是固定的。
它包含内部节点和叶节点。
内部节点
- B+树的内部节点可以包含除根节点之外的至少 n/2 个记录指针。
- 最多,树的内部节点包含n 个指针。
叶节点
- B+树的叶节点可以包含至少n/2 个记录指针和n/2个键值。
- 叶节点最多包含
n个记录指针和n个键值。 - B+树的每个叶节点包含一个块指针P以指向下一个叶节点。
在B+树中搜索记录
假设要在下面的B+树结构中搜索55。 首先,获取中间节点,该节点将指向可包含55的记录的叶节点。
因此,在中间节点中,将找到50到75个节点之间的分支。 然后在最后,重定向到第三个叶节点。这里DBMS将执行顺序搜索以找到55。
B+树插入
假设要在下面的结构中插入记录60。 它将在55之后转到第3个叶子节点。它是一个平衡树,并且该树的叶节点已经满了,所以不能在那里插入60。
在这种情况下,必须要拆分叶节点,以便可以将其插入树中而不会影响填充因子,平衡和顺序。
第3个叶节点具有值(50,55,60,65,70),其当前根节点为50。在中间拆分树的叶节点,以便不改变其平衡。 因此,可以将(50,55)和(60,65,70)分组为2个叶节点。
这两个必须是叶节点,则中间节点不能从50分支。它应该添加60,然后有一个指向新叶节点的指针。
这是在有溢出时插入条目的方法。 在正常情况下,很容易找到它所适合的节点,然后将其放在该叶节点中。
B+树删除
假设要从上面的例子中删除60。 在这种情况下需要从中间节点以及第4叶节点中删除60。 如果从中间节点中删除它,那么树将不满足B+树的规则。 所以需要修改它以获得平衡的树。
从B+树上方删除节点60并重新排列节点后,将显示如下:
DBMS哈希
在庞大的数据库结构中,搜索所有索引值并达到所需数据的效率非常低。 哈希技术用于计算磁盘上数据记录的直接位置,而不使用索引结构。
在该技术中,数据存储在通过使用哈希函数生成其地址的数据块中。 存储这些记录的存储器位置称为数据桶或数据块。
在此,哈希函数可以选择任何列值来生成地址。 大多数情况下,哈希函数使用主键来生成数据块的地址。 哈希函数是任何复杂数学函数的简单数学函数。 甚至可以将主键本身视为数据块的地址。 这意味着每个行的地址将与存储在数据块中的主键相同。
上图显示了与主键值相同的数据块地址。 这个哈希函数也可以是一个简单的数学函数,如:index,mod,cos,sin等。假设使用mod(5)哈希函数来确定数据块的地址。 在这种情况下,它在主键上应用mod(5)哈希函数,并分别生成3,3,1,4和2,并将记录存储在这些数据块地址中。
哈希的类型:
- 静态哈希
- 动态哈希
静态哈希
在静态哈希中,结果数据桶地址将始终相同。 这意味着如果使用散列函数mod(5)生成EMP_ID = 103地址,那么它将始终产生相同的桶地址3。这里,桶地址不会有任何变化。
因此,在这种静态散列中,内存中数据桶的数量始终保持不变。 在这个例子中,在内存中有五个数据桶用于存储数据。
静态哈希的操作
- 搜索记录 - 当需要搜索记录时,相同的哈希函数检索存储数据桶的地址。
- 插入记录 - 当一个新记录插入表中时,将根据哈希键为新记录生成一个地址,并将记录存储在该位置。
- 删除记录 - 要删除记录,首先获取应该删除的记录。 然后我们将在内存中删除该地址的记录。
- 更新记录 - 要更新记录,首先使用哈希函数进行搜索,然后更新数据记录。
如果想在文件中插入一些新记录,但哈希函数生成的数据桶的地址不为空,或者该地址中已存在数据。静态散列中的这种情况称为桶溢出。
要克服这种情况,有几种方法。 一些常用的方法如下:
1.打开散列
当散列函数生成已存储数据的地址时,将为其分配下一个存储桶。 这种机制称为线性探测。
2.关闭哈希
当存储桶已满时,将为相同的散列结果分配新数据存储桶,并在前一个数据存储桶之后进行链接。 这种机制称为溢出链。
例如:假设R3是需要插入表中的新地址,哈希函数为其生成地址110。 但是这个存储桶已满,用于存储新数据。 在这种情况下,在110桶的末端插入一个新桶并与之链接。
动态哈希
动态哈希方法用于克服桶溢出等静态哈希问题。
在此方法中,随着记录的增加或减少,数据桶会增大或减小。 此方法也称为可扩展哈希方法。
该方法使哈希动态化,即,它允许插入或删除而不会导致性能不佳。
如何搜索一个键
- 首先,计算键的哈希地址。
- 检查目录中使用了多少位,这些位称为
i。 - 取哈希地址的最不重要的
i位。 这给出了目录的索引。 - 现在使用索引,转到目录并查找记录可能位于的存储区地址。
如何插入新记录
- 首先,必须按照相同的步骤进行检索,最后才会进入某个存储桶。
- 如果存储桶中仍有空间,则将记录放入其中。
- 如果存储桶已满,则将拆分存储桶并重新分配记录。
示例:
考虑将以下将键分组到桶中,具体取决于其哈希地址的前缀:
2和4的最后两位是00。所以它将进入桶B0。5和6的最后两位是01,因此它将进入存储桶B1。1和3的最后两位是10,因此它将进入桶B2。7的最后两位是11,所以它将进入B3。
将带有哈希地址10001的键9插入上述结构中:
- 由于键
9具有散列地址10001,因此它必须进入第一个桶。 但是桶B1已满,所以它要分裂。 - 分裂将从
5分离5,9,因为最后三位5,9是001,所以它将进入桶B1,最后三位6是101,因此它将进入桶B5。 - 键
2和键4仍在B0中。B0中的记录由000和100条目指向,因为条目的最后两位都是00。 - 键
1和键3仍在B2中。B2中的记录由010和110条目指示,因为两个条目的最后两位都是10。 - 键
7仍在B3中。B3中的记录由111和011条目指向,因为两个条目的最后两位都是11。
动态哈希的优点
- 在这种方法中,性能不会随着系统中数据的增长而降低。它只是增加内存大小以容纳更多的数据。
- 在这种方法中,随着数据的增长和缩小,内存得到了很好的利用。不会有任何未使用的内存。
- 这种方法适用于数据增长和频繁缩小的动态数据库。
动态哈希的缺点
- 在这种方法中,如果数据大小增加,则桶大小也增加。 这些数据地址将保存在存储区地址表中。 因为随着存储桶的增长和缩小,数据地址将不断变化。 如果数据量大幅增加,则维护存储区地址表变得乏味。
- 在这种情况下,也会发生桶溢出情况。 但是,与静态哈希相比,可能需要很少时间就遇到(达到)这种情况。
DBMS静态哈希
在静态哈希中,结果数据桶地址将始终相同。 这意味着如果使用散列函数mod(5)生成EMP_ID = 103地址,那么它将始终产生相同的桶地址3。这里,桶地址不会有任何变化。
因此,在这种静态散列中,内存中数据桶的数量始终保持不变。 在这个例子中,在内存中有五个数据桶用于存储数据。
静态哈希的操作
- 搜索记录 - 当需要搜索记录时,相同的哈希函数检索存储数据桶的地址。
- 插入记录 - 当一个新记录插入表中时,将根据哈希键为新记录生成一个地址,并将记录存储在该位置。
- 删除记录 - 要删除记录,首先获取应该删除的记录。 然后我们将在内存中删除该地址的记录。
- 更新记录 - 要更新记录,首先使用哈希函数进行搜索,然后更新数据记录。
如果想在文件中插入一些新记录,但哈希函数生成的数据桶的地址不为空,或者该地址中已存在数据。静态散列中的这种情况称为桶溢出。
要克服这种情况,有几种方法。 一些常用的方法如下:
1.打开散列
当散列函数生成已存储数据的地址时,将为其分配下一个存储桶。 这种机制称为线性探测。
2.关闭哈希
当存储桶已满时,将为相同的散列结果分配新数据存储桶,并在前一个数据存储桶之后进行链接。 这种机制称为溢出链。
例如:假设R3是需要插入表中的新地址,哈希函数为其生成地址110。 但是这个存储桶已满,用于存储新数据。 在这种情况下,在110桶的末端插入一个新桶并与之链接。
DBMS动态哈希
动态哈希方法用于克服桶溢出等静态哈希问题。
在此方法中,随着记录的增加或减少,数据桶会增大或减小。 此方法也称为可扩展哈希方法。
该方法使哈希动态化,即,它允许插入或删除而不会导致性能不佳。
如何搜索一个键
- 首先,计算键的哈希地址。
- 检查目录中使用了多少位,这些位称为
i。 - 取哈希地址的最不重要的
i位。 这给出了目录的索引。 - 现在使用索引,转到目录并查找记录可能位于的存储区地址。
如何插入新记录
- 首先,必须按照相同的步骤进行检索,最后才会进入某个存储桶。
- 如果存储桶中仍有空间,则将记录放入其中。
- 如果存储桶已满,则将拆分存储桶并重新分配记录。
示例:
考虑将以下将键分组到桶中,具体取决于其哈希地址的前缀:
2和4的最后两位是00。所以它将进入桶B0。5和6的最后两位是01,因此它将进入存储桶B1。1和3的最后两位是10,因此它将进入桶B2。7的最后两位是11,所以它将进入B3。
将带有哈希地址10001的键9插入上述结构中:
- 由于键
9具有散列地址10001,因此它必须进入第一个桶。 但是桶B1已满,所以它要分裂。 - 分裂将从
5分离5,9,因为最后三位5,9是001,所以它将进入桶B1,最后三位6是101,因此它将进入桶B5。 - 键
2和键4仍在B0中。B0中的记录由000和100条目指向,因为条目的最后两位都是00。 - 键
1和键3仍在B2中。B2中的记录由010和110条目指示,因为两个条目的最后两位都是10。 - 键
7仍在B3中。B3中的记录由111和011条目指向,因为两个条目的最后两位都是11。
动态哈希的优点
- 在这种方法中,性能不会随着系统中数据的增长而降低。它只是增加内存大小以容纳更多的数据。
- 在这种方法中,随着数据的增长和缩小,内存得到了很好的利用。不会有任何未使用的内存。
- 这种方法适用于数据增长和频繁缩小的动态数据库。
动态哈希的缺点
- 在这种方法中,如果数据大小增加,则桶大小也增加。 这些数据地址将保存在存储区地址表中。 因为随着存储桶的增长和缩小,数据地址将不断变化。 如果数据量大幅增加,则维护存储区地址表变得乏味。
- 在这种情况下,也会发生桶溢出情况。 但是,与静态哈希相比,可能需要很少时间就遇到(达到)这种情况。
DBMS独立磁盘的冗余阵列(RAID)
RAID是指独立磁盘的冗余阵列。它是一种用于连接多个辅助存储设备以提高性能,数据冗余或两者兼备的技术。它能够承受一个或多个驱动器(磁盘)故障,具体取决于所使用的RAID级别。
它由一系列磁盘组成,其中连接多个磁盘以实现不同的目标。
RAID技术
RAID技术有7个级别的RAID方案。 这些模式为:RAID 0,RAID 1,....,RAID 6。
这些级别包含以下特征:
- 它包含一组物理磁盘驱动器。
- 在此技术中,操作系统将这些单独的磁盘视为单个逻辑磁盘。
- 在该技术中,数据分布在阵列的物理驱动器上。
- 冗余磁盘容量用于存储奇偶校验信息。
- 在磁盘发生故障的情况下,可以帮助奇偶校验信息恢复数据。
标准RAID级别
1. RAID 0
RAID级别0提供数据剥离,即数据可以跨多个磁盘放置。它是基于剥离意味着如果一个磁盘发生故障,那么阵列中的所有数据都将丢失。
此级别不提供容错,但会提高系统性能。
示例:
| Disk 0 | Disk 1 | Disk 2 | Disk 3 |
|---|---|---|---|
| 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 |
| 28 | 29 | 30 | 31 |
| 32 | 33 | 34 | 35 |
在上图中,没有重复数据。 因此,一旦丢失的块无法恢复。
RAID 0的优点:
- 在此级别中,吞吐量会增加,因为多个数据请求可能不在同一磁盘上。
- 此级别充分利用磁盘空间并提供高性能。
- 它至少需要2个驱动器。
RAID 0的缺点:
- 它不包含任何错误检测机制。
RAID 0 不是真正的RAID,因为它不是容错的。
在此级别中,任一磁盘发生故障都会导致相应阵列中的数据完全丢失。
2. RAID 1
此级别称为数据镜像,因为它将数据从驱动器1复制到驱动器2。它在发生故障时提供100%冗余。
示例:
| Disk 0 | Disk 1 | Disk 2 | Disk 3 |
|---|---|---|---|
| A | A | B | B |
| C | C | D | D |
| E | E | F | F |
| G | G | H | H |
只有驱动器的一半空间用于存储数据。驱动器的另一半空间是已存储数据的镜像。
RAID 1的优点:
- RAID 1的主要优点是容错。 在此级别中,如果一个磁盘发生故障,则另一个磁盘会自动接管。
- 在此级别中,即使任何一个驱动器发生故障,阵列也将起作用。
RAID 1的缺点:
- 在此级别中,每个驱动器需要一个额外的驱动器用于镜像,因此费用更高。
3. RAID 2
- RAID 2由使用汉明码奇偶校验的位级条带化组成。 在此级别中,单词中的每个数据位都记录在单独的磁盘上,数据字的ECC代码存储在不同的设置磁盘上。
- 由于其高成本和复杂结构,该水平尚未商业化使用。 RAID 3可以以较低的成本实现相同的性能。
RAID 2的优点:
- 此级别使用一个指定的驱动器来存储奇偶校验
- 它使用汉明码进行错误检测。
RAID 2的缺点:
- 它需要额外的驱动器来进行错误检测。
4. RAID 3
- RAID 3由具有专用奇偶校验的字节级条带化组成。 在此级别中,为每个磁盘部分存储奇偶校验信息并将其写入专用奇偶校验驱动器。
- 在驱动器发生故障的情况下,访问奇偶校验驱动器,并从其余设备重建数据。 更换故障驱动器后,可以在新驱动器上恢复丢失的数据。
- 在此级别,数据可以批量传输。 因此,高速数据传输是可能的。
| Disk 0 | Disk 1 | Disk 2 | Disk 3 |
|---|---|---|---|
| A | B | C | P(A, B, C) |
| D | E | F | P(D, E, F) |
| G | H | I | P(G, H, I) |
| J | K | L | P(J, K, L) |
RAID 3的优点:
- 在此级别中,使用奇偶校验驱动器重新生成数据。
- 它包含高数据传输速率。
- 在此级别中,并行访问数据。
RAID 3的缺点:
- 它需要一个额外的平价驱动器。
- 它为小型文件的操作提供了缓慢的性能。
5. RAID 4
- RAID 4包括使用奇偶校验磁盘进行块级剥离。 RAID 4采用基于奇偶校验的方法,而不是复制数据。
- 由于奇偶校验的工作方式,此级别允许最多恢复1个磁盘故障。 在此级别中,如果多个磁盘发生故障,则无法恢复数据。
- 级别3和级别4都需要至少三个磁盘才能实现RAID。
| Disk 0 | Disk 1 | Disk 2 | Disk 3 |
|---|---|---|---|
| A | B | C | P0 |
| D | E | F | P1 |
| G | H | I | P2 |
| J | K | L | P3 |
在此图中,可以观察到一个专用于奇偶校验的磁盘。
在此级别中,可以使用XOR函数计算奇偶校验。 如果数据位为0,0,0,1,那么奇偶校验位为XOR(0,1,0,0)= 1。如果奇偶校验位为0,0,1,1,则奇偶校验位为XOR(0,0,1,1)= 0。这意味着,偶数个数导致奇偶校验0,奇数个数导致奇偶校验1。
| C1 | C2 | C3 | C4 | Parity |
|---|---|---|---|---|
| 0 | 1 | 0 | 0 | 1 |
| 0 | 0 | 1 | 1 | 0 |
假设在上图中,C2由于某些磁盘故障而丢失。 然后使用所有其他列的值和奇偶校验位,可以重新计算存储在C2中的数据位。 此级别允许恢复丢失的数据。
6. RAID 5
- RAID 5是对RAID 4系统的略微修改。唯一的区别是在RAID 5中,奇偶校验在驱动器之间旋转。
- 它由带有DISTRIBUTED奇偶校验的块级条带化组成。
- 与RAID 4相同,此级别允许最多恢复1个磁盘故障。 如果多个磁盘发生故障,则无法进行数据恢复。
| Disk 0 | Disk 1 | Disk 2 | Disk 3 | Disk 4 |
|---|---|---|---|---|
| 0 | 1 | 2 | 3 | P0 |
| 5 | 6 | 7 | P1 | 4 |
| 10 | 11 | P2 | 8 | 9 |
| 15 | P3 | 12 | 13 | 14 |
| P4 | 16 | 17 | 18 | 19 |
该表显示了奇偶校验位如何旋转。引入此级别是为了使随机写入性能更好。
RAID 5的优点:
- 该级别具有成本效益并且提供高性能。
- 在此级别中,奇偶校验分布在阵列中的磁盘上。
- 它用于使随机写入性能更好。
RAID 5的缺点:
- 在此级别中,磁盘故障恢复需要较长时间,因为必须从所有可用驱动器计算奇偶校验。
- 并发驱动器故障时,此级别无法生存。
7. RAID 6
- 此级别是RAID 5的扩展。它包含具有2个奇偶校验位的块级剥离。
- 在RAID 6中,可以承受2个并发磁盘故障。 假设使用的是RAID 5和RAID 1。当磁盘发生故障时,需要更换故障磁盘,如果同时另一个磁盘发生故障,那么将无法恢复任何数据。因此在这种情况下,可以使用两个并发磁盘故障中幸存的部分。
| Disk 1 | Disk 2 | Disk 3 | Disk 4 |
|---|---|---|---|
| A0 | B0 | Q0 | P0 |
| A1 | Q1 | P1 | D1 |
| Q2 | P2 | C2 | D2 |
| P3 | B3 | C3 | Q3 |
RAID 6的优点:
- 此级别执行RAID 0以剥离数据,RAID 1执行镜像。 在此级别中,在镜像之前执行剥离。
- 在此级别中,所需的驱动器应为2的倍数。
RAID 6的缺点:
- 它没有使用100%磁盘功能,因为一半用于镜像。
- 它包含的可伸缩性非常有限。
DBMS SQL简介
SQL简介-
SQL代表结构化查询语言。它用于存储和管理关系数据库管理系统(RDMS)中的数据。
它是关系数据库系统的标准语言。它让用户能够创建,读取,更新和删除关系数据库和表。
MySQL,Informix,Oracle,MS Access和SQL Server等所有RDBMS都使用SQL作为标准数据库语言。
SQL允许用户使用类似英语的语句以多种方式查询数据库。
规则
SQL遵循以下规则:
- 结构查询语言不区分大小写。 通常,SQL的关键字以大写形式编写。
- SQL语句依赖于文本行,可以在一个或多个文本行上使用单个SQL语句。
- 使用SQL语句,可以执行数据库中的大多数操作。
- SQL依赖于元组关系演算和关系代数。
SQL过程
- 当RDBMS执行SQL命令时,系统会找出执行请求的最佳方法,而SQL引擎会确定如何解释该任务。
- 在该过程中,包括各种组件。 这些组件可以是优化引擎,查询引擎,查询调度程序,经典查询引擎等。
- 所有非SQL查询都由经典查询引擎处理,但SQL查询引擎不会处理逻辑文件。
DBMS SQL特点
- SQL很容易学习。
- SQL用于访问关系数据库管理系统中的数据。
- SQL可以对数据库执行查询。
- SQL用于描述数据。
- SQL用于定义数据库中的数据并在需要时对其进行操作。
- SQL用于创建和删除数据库和表。
- SQL用于在数据库中创建视图,存储过程和函数。
- SQL允许用户设置表,过程和视图的权限。
SQL的优点
SQL有以下优点:
- 快速 - 使用SQL查询,用户可以快速有效地从数据库中检索大量记录。
- 无需编码 - 在标准SQL中,管理数据库系统非常容易。它不需要大量代码来管理数据库系统。
- 明确界定标准 - ISO和ANSI是长期建立使用的SQL数据库标准。
- 可移植性 - SQL可用于笔记本电脑,PC,服务器甚至某些手机。
- 互动语言 - SQL是用于与数据库通信的域语言。 它还用于在几秒钟内接收复杂问题的答案。
- 多个数据视图 - 使用SQL语言,用户可以对数据库结构进行不同的视图。
SQL数据类型
SQL数据类型 -
- SQL数据类型用于定义列可以包含的值。
- 每列都需要在数据库表中具有名称和数据类型。
SQL的数据类型:
1. 二进制数据类型
下面给出了三种类型的二进制数据类型:
| 数据类型 | 描述 |
|---|---|
binary |
它的最大长度为8000字节,包含固定长度的二进制数据。 |
varbinary |
它的最大长度为8000字节,包含可变长度的二进制数据。 |
image |
它的最大长度为2,147,483,647字节,包含可变长度的二进制数据。 |
2. 近似数值数据类型:
子类型如下:
| 类型 | 开始 | 结束 | 描述 |
|---|---|---|---|
float |
-1.79E + 308 |
1.79E + 308 |
它用于指定浮点值,例如 - 6.2,2.9等 |
real |
-3.40e + 38 |
3.40E + 38 |
它指定单精度浮点数 |
3. 精确数字数据类型
子类型如下:
| 数据类型 | 描述 |
|---|---|
int |
它用于指定整数值。 |
smallint |
它用于指定小整数值。 |
bit |
它具有要存储的位数。 |
decimal |
它指定一个可以包含十进制数的数值。 |
numeric |
它用于指定数值。 |
4. 字符串数据类型
子类型如下:
| 数据类型 | 描述 |
|---|---|
char |
它的最大长度为8000个字符,包含固定长度的非unicode字符。 |
varchar |
它的最大长度为8000个字符,包含可变长度的非unicode字符。 |
text |
它的最大长度为2,147,483,647个字符,包含可变长度的非unicode字符。 |
5. 日期和时间数据类型
子类型如下:
| 数据类型 | 描述 |
|---|---|
date |
它用于存储年,月和日值。 |
time |
它用于存储小时,分钟和秒值。 |
timestamp |
它存储年,月,日,小时,分钟和第二个值。 |
SQL命令
SQL命令是指令,它用于与数据库通信交互。 它还用于执行特定任务,功能和数据查询。
SQL可以执行各种任务,如创建表,向表中添加数据,删除表,修改表,为用户设置权限等。
SQL命令的类型,如下图所示 :
1. 数据定义语言(DDL)
- DDL更改表的结构,如创建表,删除表,更改表等。
- DDL的所有命令都是自动提交的,这意味着它会永久保存数据库中的所有更改。
以下是DDL下的一些命令:
- CREATE
- ALTER
- DROP
- TRUNCATE
CREATE:用于在数据库中创建新表。
语法:
CREATE TABLE TABLE_NAME (COLUMN_NAME DATATYPES[,....]);
示例
CREATE TABLE EMPLOYEE( Name VARCHAR2(20), Email VARCHAR2(100), DOB DATE );
DROP:用于删除表中存储的结构和记录。
语法:
DROP TABLE ;
示例
DROP TABLE EMPLOYEE;
ALTER:它用于改变数据库的结构。此更改可以是修改现有属性,也可以是添加新属性。
语法:
向表中添加新列 -
ALTER TABLE table_name ADD column_name COLUMN-definition;
要修改表中的现有列:
ALTER TABLE MODIFY(COLUMN DEFINITION....);
示例
ALTER TABLE STU_DETAILS ADD(ADDRESS VARCHAR2(20)); ALTER TABLE STU_DETAILS MODIFY (NAME VARCHAR2(20));
TRUNCATE:用于删除表中的所有行并释放包含该表的空格。
语法:
TRUNCATE TABLE table_name;
示例:
TRUNCATE TABLE EMPLOYEE;
2.数据操作语言
DML命令用于修改数据库,它负责数据库中的所有形式的更改。
DML的命令不是自动提交的,这意味着它无法永久保存数据库中的所有更改。也可以回滚。
以下是DML下的一些命令:
- INSERT
- UPDATE
- DELETE
INSERT:INSERT语句是SQL查询,它用于将数据插入表的行。
语法:
INSERT INTO TABLE_NAME (col1, col2, col3,.... col N) VALUES (value1, value2, value3, .... valueN);
或者,
INSERT INTO TABLE_NAME VALUES (value1, value2, value3, .... valueN);
示例 -
INSERT INTO tb_yiibai (Author, Subject) VALUES ("Maxsu", "DBMS");
UPDATE:此命令用于更新或修改表中列的值。
语法:
UPDATE table_name SET [column_name1= value1,...column_nameN = valueN] [WHERE CONDITION]
示例
UPDATE students SET User_Name = 'Yiibai' WHERE Student_Id = '3'
DELETE:用于从表中删除一行或多行。
语法:
DELETE FROM table_name [WHERE condition];
示例
DELETE FROM tb_yiibai WHERE Author="Maxsu";
3. 数据控制语言
DCL命令用于授予和恢复任何数据库用户的权限。
以下是DCL下的一些命令:
- Grant
- Revoke
Grant:用于授予用户对数据库的访问权限。
示例
GRANT SELECT, UPDATE ON MY_TABLE TO SOME_USER, ANOTHER_USER;
Revoke:它用于从用户收回权限。
示例
REVOKE SELECT, UPDATE ON MY_TABLE FROM USER1, USER2;
4. 事务控制语言
TCL命令只能用于INSERT,DELETE和UPDATE等DML命令。
这些操作会自动在数据库中提交,这就是创建表或删除表时无法使用它们的原因。
以下是TCL下的一些命令:
- COMMIT
- ROLLBACK
- SAVEPOINT
Commit:Commit命令用于将所有事务保存到数据库。
语法
COMMIT;
示例
DELETE FROM CUSTOMERS WHERE AGE = 25; COMMIT;
Rollback:回滚命令用于撤消尚未保存到数据库的事务。
语法:
ROLLBACK;
示例
DELETE FROM CUSTOMERS WHERE AGE = 25; ROLLBACK;
SAVEPOINT:用于将事务回滚到某个点而不回滚整个事务。
语法:
SAVEPOINT SAVEPOINT_NAME;
5. 数据查询语言
DQL用于从数据库中获取数据。
它只使用一个命令:
- SELECT
SELECT:这与关系代数的投影操作相同。它用于根据WHERE子句描述的条件选择属性。
语法
SELECT expressions FROM TABLES WHERE conditions;
示例
SELECT emp_name FROM employee WHERE age > 20;
SQL运算符
SQL有各种类型的运算符:
SQL算术运算符
假设有两个变量:变量'a'和变量'b'。 这里,'a'包含的值为20,'b'的值包含10。
| 操作符 | 描述 | 示例 |
|---|---|---|
+ |
相加两个操作数的值。 | a+b 的结果为 30 |
- |
从左侧操作数中减去右侧操作数。 | a-b 的结果为 10 |
* |
用于将两个操作数的值相乘。 | a*b 的结果为 200 |
/ |
用于将左侧操作数除以右侧操作数。 | a/b 的结果为 2 |
% |
用于将左侧操作数除以右侧操作数并返回余数。 | a%b 的结果为 0 |
SQL比较运算符
假设有两个变量:变量'a'和变量'b'。 这里,'a'包含的值为20,'b'的值包含10。
| 运算符 | 描述 | 示例 |
|---|---|---|
= |
检查两个操作数值是否相等,如果值相等则条件变为真。 | (a=b)结果为假。 |
!= |
它检查两个操作数值是否相等,如果值不相等,则条件变为真。 | (a!=b)结果为真。 |
<> |
它检查两个操作数值是否相等,如果值不相等,则条件变为真。 | (a<>b)结果为真。 |
> |
它检查左操作数值是否大于右操作数值,如果是,则条件变为真。 | (a>b) 结果为假 |
< |
它检查左操作数值是小于右操作数值,如果是,则条件变为真。 | (a<b) 结果为真 |
>= |
它检查左操作数值是否大于或等于右操作数值,如果是,则条件变为真。 | (a>=b)结果为假。 |
<= |
它检查左操作数值是否小于或等于右操作数值,如果是,则条件变为真。 | (a<=b)结果为真 |
!< |
它检查左操作数值是否不小于右操作数值,如果是,则条件变为真。 | (a!<b)结果为假 |
!> |
它检查左操作数值是否不大于右操作数值,如果是,则条件变为真。 | (a!>b)结果为真 |
SQL逻辑运算符
SQL中使用以下逻辑运算符:
| 操作符 | 描述 |
|---|---|
ALL |
它将值与另一个值集中的所有值进行比较。 |
AND |
它允许在SQL语句中存在多个条件。 |
ANY |
它根据条件比较列表中的值。 |
BETWEEN |
它用于搜索一组值内的值。 |
IN |
它将值与指定的列表值进行比较。 |
NOT |
它可以颠倒任何逻辑运算符的含义。 |
OR |
它结合了SQL语句中的多个条件。 |
EXISTS |
它用于搜索指定表中是否存在行。 |
LIKE |
它使用通配符运算符将值与类似值进行比较。 |
SQL表
SQL表是按行和列组织的数据集合。在DBMS中,表称为关系,行称为元组。
表是一种简单的数据存储形式。表也被视为关系的方便表示。
下面来看看一个表:EMPLOYEE 的示例:
| EMP_ID | EMP_NAME | CITY | PHONE_NO |
|---|---|---|---|
| 1 | Kristen | Washington | 7289201223 |
| 2 | Anna | Franklin | 9378282882 |
| 3 | Jackson | Bristol | 9264783838 |
| 4 | Kellan | California | 7254728346 |
| 5 | Ashley | Hawaii | 9638482678 |
在上表中,“EMPLOYEE”是表名,“EMP_ID”,“EMP_NAME”,“CITY”,“PHONE_NO”是列名。 多列数据的组合形成一行,例如:1,“Kristen”,“Washington”和7289201223是一行的数据。
在表上的操作有
- 创建表
- 丢弃表
- 删除表
- 重命名表
1. SQL创建表
SQLcreate table用于在数据库中创建表。 要定义表,应该定义表的名称,并定义其列和列的数据类型。
语法
create table "table_name"
("column1" "data type",
"column2" "data type",
"column3" "data type",
...
"columnN" "data type");
示例
SQL> CREATE TABLE EMPLOYEE ( EMP_ID INT NOT NULL, EMP_NAME VARCHAR (25) NOT NULL, PHONE_NO INT NOT NULL, ADDRESS CHAR (30), PRIMARY KEY (ID) );
如果成功创建表,则可以通过SQL Server查看消息来验证表。 也可以使用DESC命令,如下所示:
SQL> DESC EMPLOYEE;
| Field | Type | Null | Key | Default | Extra |
|---|---|---|---|---|---|
| EMP_ID | int(11) | NO | PRI | NULL | |
| EMP_NAME | varchar(25) | NO | NULL | ||
| PHONE_NO | NO | int(11) | NULL | ||
| ADDRESS | YES | NULL | char(30) |
现在,在数据库中有一张EMPLOYEE表,可以用来存储员工相关的信息。
删除表
SQL删除表用于删除表定义和表中的所有数据。 执行此命令时,表中可用的所有信息将永久丢失,因此在使用此命令时必须非常小心。
语法
DROP TABLE "table_name";
首先,需要使用以下命令验证EMPLOYEE表:
SQL> DESC EMPLOYEE;
| Field | Type | Null | Key | Default | Extra |
|---|---|---|---|---|---|
| EMP_ID | int(11) | NO | PRI | NULL | |
| EMP_NAME | varchar(25) | NO | NULL | ||
| PHONE_NO | NO | int(11) | NULL | ||
| ADDRESS | YES | NULL | char(30) |
此表显示EMPLOYEE表在数据库中可用,因此可以按如下方式删除它:
SQL> DROP TABLE EMPLOYEE;
现在,可以使用以下命令检查表是否存在:
Query OK, 0 rows affected (0.01 sec)
由于这表明该表已被删除,因此它不会显示它。
SQL DELETE表
在SQL中,DELETE语句用于从表中删除行记录。使用WHERE条件从表中删除特定行。 如果要删除表中的所有记录,则不需要使用WHERE子句。
语法
DELETE FROM table_name WHERE condition;
示例
假设,EMPLOYEE表中具有以下记录:
| EMP_ID | EMP_NAME | CITY | PHONE_NO | SALARY |
|---|---|---|---|---|
| 1 | Kristen | Chicago | 9737287378 | 150000 |
| 2 | Russell | Austin | 9262738271 | 200000 |
| 3 | Denzel | Boston | 7353662627 | 100000 |
| 4 | Angelina | Denver | 9232673822 | 600000 |
| 5 | Robert | Washington | 9367238263 | 350000 |
| 6 | Christian | Los angels | 7253847382 | 260000 |
以下查询将删除ID为3的员工。
SQL> DELETE FROM EMPLOYEE WHERE EMP_ID = 3;
现在,EMPLOYEE表将具有以下记录。
| EMP_ID | EMP_NAME | CITY | PHONE_NO | SALARY |
|---|---|---|---|---|
| 1 | Kristen | Chicago | 9737287378 | 150000 |
| 2 | Russell | Austin | 9262738271 | 200000 |
| 4 | Angelina | Denver | 9232673822 | 600000 |
| 5 | Robert | Washington | 9367238263 | 350000 |
| 6 | Christian | Los angels | 7253847382 | 260000 |
如果未指定WHERE条件,则会删除表中所有行。
DELETE FROM EMPLOYEE;
现在,EMPLOYEE表没有任何记录。
SQL SELECT语句
在SQL中,SELECT语句用于从数据库中的表中查询或检索数据。 返回存储在表中的数据,返回的结果称为结果集。
语法
SELECT column1, column2, ... FROM table_name;
这里,表达式是要从中选择数据的表的字段名称。使用以下语法选择表中可用的所有字段:
SELECT * FROM table_name;
假设EMPLOYEE表有以下行记录 -
| EMP_ID | EMP_NAME | CITY | PHONE_NO | SALARY |
|---|---|---|---|---|
| 1 | Kristen | Chicago | 9737287378 | 150000 |
| 2 | Russell | Austin | 9262738271 | 200000 |
| 3 | Angelina | Denver | 9232673822 | 600000 |
| 4 | Robert | Washington | 9367238263 | 350000 |
| 5 | Christian | Los angels | 7253847382 | 260000 |
要获取所有员工的EMP_ID,请使用以下查询:
SELECT EMP_ID FROM EMPLOYEE;
查询得到结果如下 -
EMP_ID ----------------------------- 1 2 3 4 5
要获取EMP_NAME和SALARY,请使用以下查询:
SELECT EMP_NAME, SALARY FROM EMPLOYEE;
查询得到结果如下 -
EMP_NAME SALARY --------------------------------------- Kristen 150000 Russell 200000 Angelina 600000 Robert 350000 Christian 260000
要获取EMPLOYEE表中所有字段,请使用以下查询:
SELECT * FROM EMPLOYEE
执行上面查询语句,得到以下结果:
| EMP_ID | EMP_NAME | CITY | PHONE_NO | SALARY |
|---|---|---|---|---|
| 1 | Kristen | Chicago | 9737287378 | 150000 |
| 2 | Russell | Austin | 9262738271 | 200000 |
| 3 | Angelina | Denver | 9232673822 | 600000 |
| 4 | Robert | Washington | 9367238263 | 350000 |
| 5 | Christian | Los angels | 7253847382 | 260000 |
SQL INSERT语句
SQL INSERT语句用于在表中插入单个或多个数据。 在SQL中,可以通过以下两种方式插入数据:
- 不指定列名称
- 通过指定列名称
假设有一个表:EMPLOYEE的结构和数据记录如下 -
| EMP_ID | EMP_NAME | CITY | SALARY | AGE |
|---|---|---|---|---|
| 1 | Angelina | Chicago | 200000 | 30 |
| 2 | Robert | Austin | 300000 | 26 |
| 3 | Christian | Denver | 100000 | 42 |
| 4 | Kristen | Washington | 500000 | 29 |
| 5 | Russell | Los angels | 200000 | 36 |
1.不指定列名
如果要指定所有列值,可以指定或忽略列值。
语法
INSERT INTO TABLE_NAME VALUES (value1, value2, value 3, .... Value N);
插入语句
INSERT INTO EMPLOYEE VALUES (6, 'Marry', 'Canada', 600000, 48);
执行此查询后,EMPLOYEE表中的数据如下所示:
| EMP_ID | EMP_NAME | CITY | SALARY | AGE |
|---|---|---|---|---|
| 1 | Angelina | Chicago | 200000 | 30 |
| 2 | Robert | Austin | 300000 | 26 |
| 3 | Christian | Denver | 100000 | 42 |
| 4 | Kristen | Washington | 500000 | 29 |
| 5 | Russell | Los angels | 200000 | 36 |
| 6 | Marry | Canada | 600000 | 48 |
2.通过指定列名称
要插入部分列值,必须指定列名称。
语法
INSERT INTO TABLE_NAME [(col1, col2, col3,.... col N)] VALUES (value1, value2, value 3, .... Value N);
插入语句
INSERT INTO EMPLOYEE (EMP_ID, EMP_NAME, AGE) VALUES (7, 'Jack', 40);
执行此查询后,EMPLOYEE表中的数据如下所示:
| EMP_ID | EMP_NAME | CITY | SALARY | AGE |
|---|---|---|---|---|
| 1 | Angelina | Chicago | 200000 | 30 |
| 2 | Robert | Austin | 300000 | 26 |
| 3 | Christian | Denver | 100000 | 42 |
| 4 | Kristen | Washington | 500000 | 29 |
| 5 | Russell | Los angels | 200000 | 36 |
| 6 | Marry | Canada | 600000 | 48 |
| 7 | Jack | null | null | 40 |
SQL UPDATE语句
SQL UPDATE语句用于修改数据库中已有的数据。WHERE子句中的条件决定要更新哪一行。
语法
UPDATE table_name SET column1 = value1, column2 = value2, ... WHERE condition;
假设有一个EMPLOYEE表,它的结构和数据记录如下所示 -
| EMP_ID | EMP_NAME | CITY | SALARY | AGE |
|---|---|---|---|---|
| 1 | Angelina | Chicago | 200000 | 30 |
| 2 | Robert | Austin | 300000 | 26 |
| 3 | Christian | Denver | 100000 | 42 |
| 4 | Kristen | Washington | 500000 | 29 |
| 5 | Russell | Los angels | 200000 | 36 |
| 6 | Marry | Canada | 600000 | 48 |
更新单个记录
更新EMP_NAME列,并在SALARY为500000的行中将值设置为“Emma”。
语法
UPDATE table_name SET column_name = value WHERE condition;
查询语句 -
UPDATE EMPLOYEE SET EMP_NAME = 'Emma' WHERE SALARY = 500000;
执行此查询后,EMPLOYEE表将如下所示:
| EMP_ID | EMP_NAME | CITY | SALARY | AGE |
|---|---|---|---|---|
| 1 | Angelina | Chicago | 200000 | 30 |
| 2 | Robert | Austin | 300000 | 26 |
| 3 | Christian | Denver | 100000 | 42 |
| 4 | Emma | Washington | 500000 | 29 |
| 5 | Russell | Los angels | 200000 | 36 |
| 6 | Marry | Canada | 600000 | 48 |
更新多条记录
如果要更新多个列,则应将用逗号分配的每个字段分开。 在EMPLOYEE表中,将EMP_NAME列更新为“Kevin”,将CITY更新为“Boston”,指定EMP_ID为5。
语法
UPDATE table_name SET column_name = value1, column_name2 = value2 WHERE condition;
查询语句
UPDATE EMPLOYEE SET EMP_NAME = 'Kevin', City = 'Boston' WHERE EMP_ID = 5;
查询结果 -
| EMP_ID | EMP_NAME | CITY | SALARY | AGE |
|---|---|---|---|---|
| 1 | Angelina | Chicago | 200000 | 30 |
| 2 | Robert | Austin | 300000 | 26 |
| 3 | Christian | Denver | 100000 | 42 |
| 4 | Kristen | Washington | 500000 | 29 |
| 5 | Kevin | Boston | 200000 | 36 |
| 6 | Marry | Canada | 600000 | 48 |
不使用WHERE子句
如果要更新表中的所有行,则不需要使用WHERE子句。 在EMPLOYEE表中,将EMP_NAME列更新为“Harry”。
语法
UPDATE table_name SET column_name = value1;
查询语句如下 -
UPDATE EMPLOYEE SET EMP_NAME = 'Harry';
执行上面语句,得到以下结果 -
| EMP_ID | EMP_NAME | CITY | SALARY | AGE |
|---|---|---|---|---|
| 1 | Harry | Chicago | 200000 | 30 |
| 2 | Harry | Austin | 300000 | 26 |
| 3 | Harry | Denver | 100000 | 42 |
| 4 | Harry | Washington | 500000 | 29 |
| 5 | Harry | Los angels | 200000 | 36 |
| 6 | Harry | Canada | 600000 | 48 |
SQL DELETE语句
SQL DELETE语句用于从表中删除行。 通常,DELETE语句从表中删除一个或多个记录。
语法
DELETE FROM table_name WHERE some_condition;
假设有一张:EMPLOYEE的结构和行记录得到以下结果:
| EMP_ID | EMP_NAME | CITY | SALARY | AGE |
|---|---|---|---|---|
| 1 | Angelina | Chicago | 200000 | 30 |
| 2 | Robert | Austin | 300000 | 26 |
| 3 | Christian | Denver | 100000 | 42 |
| 4 | Kristen | Washington | 500000 | 29 |
| 5 | Russell | Los angels | 200000 | 36 |
| 6 | Marry | Canada | 600000 | 48 |
删除单个记录
要删除表EMPLOYEE中EMP_NAME ='Kristen'的行,这将仅删除第四行。
查询语句 -
DELETE FROM EMPLOYEE WHERE EMP_NAME = 'Kristen';
执行此查询后,EMPLOYEE表将如下所示:
| EMP_ID | EMP_NAME | CITY | SALARY | AGE |
|---|---|---|---|---|
| 1 | Angelina | Chicago | 200000 | 30 |
| 2 | Robert | Austin | 300000 | 26 |
| 3 | Christian | Denver | 100000 | 42 |
| 5 | Russell | Los angels | 200000 | 36 |
| 6 | Marry | Canada | 600000 | 48 |
删除多个记录
从EMPLOYEE表中删除AGE为30的行。这将删除两行(第一行和第三行)。
查询语句:
DELETE FROM EMPLOYEE WHERE AGE= 30;
执行此查询后,EMPLOYEE表将如下所示:
| EMP_ID | EMP_NAME | CITY | SALARY | AGE |
|---|---|---|---|---|
| 2 | Robert | Austin | 300000 | 26 |
| 3 | Christian | Denver | 100000 | 42 |
| 5 | Russell | Los angels | 200000 | 36 |
| 6 | Marry | Canada | 600000 | 48 |
删除所有记录
要删除EMPLOYEE表中的所有行。 在执行此查询之后,EMPLOYEE表中不再有记录。
语法
DELETE * FROM table_name; # 或者 DELETE FROM table_name;
查询语句 -
DELETE FROM EMPLOYEE;
执行此查询后,EMPLOYEE表所有记录被删除。
SQL视图
SQL中的视图被视为虚拟表。视图还包含行和列。
要创建视图,可以从数据库中存在的一个或多个表中选择字段。
视图可以具有基于特定条件的特定行或表的所有行。
假设有以下几张表:
Student_Detail表的结构和数据 -
| STU_ID | NAME | ADDRESS |
|---|---|---|
| 1 | Stephan | Delhi |
| 2 | Kathrin | Noida |
| 3 | David | Ghaziabad |
| 4 | Alina | Gurugram |
Student_Marks表的结构和数据 -
| STU_ID | NAME | MARKS | AGE |
|---|---|---|---|
| 1 | Stephan | 97 | 19 |
| 2 | Kathrin | 86 | 21 |
| 3 | David | 74 | 18 |
| 4 | Alina | 90 | 20 |
| 5 | John | 96 | 18 |
1. 创建视图
可以使用CREATE VIEW语句创建视图。可以从单个表或多个表创建视图。
语法:
CREATE VIEW view_name AS SELECT column1, column2..... FROM table_name WHERE condition;
2.从单个表创建视图
在此示例中,从表Student_Detail创建一个名称为DetailsView的视图。
CREATE VIEW DetailsView AS SELECT NAME, ADDRESS FROM Student_Details WHERE STU_ID < 4;
就像表查询一样,可以查询视图来查看数据。
SELECT * FROM DetailsView;
查询得到结果如下 -
NAME ADDRESS ---------------------------------- Stephan Delhi Kathrin Noida David Ghaziabad
3.从多个表创建视图
只需在SELECT语句中包含多个表,即可创建多个表中的视图。
在给定的示例中,从两个表Student_Detail和Student_Marks创建名称为:MarksView的视图。
创建视图语句:
CREATE VIEW MarksView AS SELECT Student_Detail.NAME, Student_Detail.ADDRESS, Student_Marks.MARKS FROM Student_Detail, Student_Mark WHERE Student_Detail.NAME = Student_Marks.NAME;
查询显示视图 -MarksView的数据的语句:
SELECT * FROM MarksView;
得到以下结果:
| NAME | ADDRESS | MARKS |
|---|---|---|
| Stephan | Delhi | 97 |
| Kathrin | Noida | 86 |
| David | Ghaziabad | 74 |
| Alina | Gurugram | 90 |
4.删除视图
可以使用Drop View语句删除视图。
语法
DROP VIEW view_name;
如果要删除视图 -MarksView,可以使用以下语句:
DROP VIEW MarksView;
SQL索引
索引是特殊的查找表。它用于快速地从数据库中检索数据。
索引用于加速选择查询和where子句。 但它使用insert和update语句时速度较慢。可以在不影响数据的情况下创建或删除索引。
数据库中的索引就像书本前面或后面的目录(索引)一样。
例如:当引用书中讨论某个主题的所有页面时,首先查看书本的目录索引,该索引按字母顺序列出所有主题,然后引用一个或多个特定页码。
1.创建索引语句
它用于在表上创建索引,它允许重复值。
语法
CREATE INDEX index_name ON table_name (column1, column2, ...);
示例
CREATE INDEX idx_name ON Persons (LastName, FirstName);
2.唯一索引声明
它用于在表上创建唯一索引,它不允许有重复值。
语法
CREATE UNIQUE INDEX index_name ON table_name (column1, column2, ...);
示例
CREATE UNIQUE INDEX websites_idx ON websites (site_name);
3.删除索引语句
它用于删除表中的索引。
语法
DROP INDEX index_name;
示例
DROP INDEX websites_idx;
SQL子查询
子查询是另一个SQL查询中的查询,并嵌入在WHERE子句中。
重要规则:
- 子查询可以放在许多SQL子句中,如
WHERE子句,FROM子句,HAVING子句。 - 可以将子查询与
SELECT,UPDATE,INSERT,DELETE语句以及=,<,>,>=,<=,IN,BETWEEN等运算符一起使用。 - 子查询是另一个查询中的查询。外部查询称为主查询,内部查询称为子查询。
- 子查询位于比较运算符的右侧。
- 子查询括在括号中。
- 在子查询中,不能使用
ORDER BY命令。 但GROUP BY命令可用于执行与ORDER BY命令相同的功能。
1.带有Select语句的子查询
SQL子查询最常与Select语句一起使用。
语法
SELECT column_name FROM table_name WHERE column_name expression operator ( SELECT column_name from table_name WHERE ... );
示例
假设EMPLOYEE表有以下记录:
| ID | NAME | AGE | ADDRESS | SALARY |
|---|---|---|---|---|
| 1 | John | 20 | US | 2000.00 |
| 2 | Stephan | 26 | Dubai | 1500.00 |
| 3 | David | 27 | Bangkok | 2000.00 |
| 4 | Alina | 29 | UK | 6500.00 |
| 5 | Kathrin | 34 | Bangalore | 8500.00 |
| 6 | Harry | 42 | China | 4500.00 |
| 7 | Jackson | 25 | Mizoram | 10000.00 |
带有SELECT语句的子查询将是:
SELECT * FROM EMPLOYEE WHERE ID IN (SELECT ID FROM EMPLOYEE WHERE SALARY > 4500);
这将产生以下结果:
| ID | NAME | AGE | ADDRESS | SALARY |
|---|---|---|---|---|
| 4 | Alina | 29 | UK | 6500.00 |
| 5 | Kathrin | 34 | Bangalore | 8500.00 |
| 7 | Jackson | 25 | Mizoram | 10000.00 |
2.带有INSERT语句的子查询
SQL子查询也可以与Insert语句一起使用。 在insert语句中,子查询返回的数据用于插入另一个表。
在子查询中,可以使用任何字符,日期函数修改所选数据。
语法:
INSERT INTO table_name (column1, column2, column3....) SELECT * FROM table_name WHERE VALUE OPERATOR
示例
假设有一个与EMPLOYEE类似的表EMPLOYEE_BKP。现在使用以下语法将完整的EMPLOYEE表复制到EMPLOYEE_BKP表中。
INSERT INTO EMPLOYEE_BKP SELECT * FROM EMPLOYEE WHERE ID IN (SELECT ID FROM EMPLOYEE);
3.带有UPDATE语句的子查询
SQL的子查询可以与Update语句一起使用。 当子查询与Update语句一起使用时,可以更新表中的单个列或多个列。
语法
UPDATE table SET column_name = new_value WHERE VALUE OPERATOR (SELECT COLUMN_NAME FROM TABLE_NAME WHERE condition);
示例
假设有一个EMPLOYEE_BKP表,它是EMPLOYEE表的备份。要在EMPLOYEE表中为所有AGE大于或等于29的员工更新SALARY值更新增加0.25倍。
UPDATE EMPLOYEE SET SALARY = SALARY * 0.25 WHERE AGE IN (SELECT AGE FROM CUSTOMERS_BKP WHERE AGE >= 29);
上面命令将影响三行,最后,EMPLOYEE表的记录更新为如下。
| ID | NAME | AGE | ADDRESS | SALARY |
|---|---|---|---|---|
| 1 | John | 20 | US | 2000.00 |
| 2 | Stephan | 26 | Dubai | 1500.00 |
| 3 | David | 27 | Bangkok | 2000.00 |
| 4 | Alina | 29 | UK | 1625.00 |
| 5 | Kathrin | 34 | Bangalore | 2125.00 |
| 6 | Harry | 42 | China | 1125.00 |
| 7 | Jackson | 25 | Mizoram | 10000.00 |
4.带有DELETE语句的子查询
SQL的子查询可以与Delete语句一起使用,就像上面提到的任何其他语句一样。
语法
DELETE FROM TABLE_NAME WHERE VALUE OPERATOR (SELECT COLUMN_NAME FROM TABLE_NAME WHERE condition);
示例
假设有一张EMPLOYEE_BKP表,它是EMPLOYEE表的备份。要从EMPLOYEE表中删除AGE大于或等于29的所有记录。参考以下语句 -
DELETE FROM EMPLOYEE WHERE AGE IN (SELECT AGE FROM EMPLOYEE_BKP WHERE AGE >= 29 );
这将影响三行,最后,EMPLOYEE表将具有以下记录。
| ID | NAME | AGE | ADDRESS | SALARY |
|---|---|---|---|---|
| 1 | John | 20 | US | 2000.00 |
| 2 | Stephan | 26 | Dubai | 1500.00 |
| 3 | David | 27 | Bangkok | 2000.00 |
| 7 | Jackson | 25 | Mizoram | 10000.00 |
SQL子句
以下是一些觉的SQL子句:
1. GROUP BY
- SQL
GROUP BY语句用于将相同的数据排列到分组中。GROUP BY语句与SQL SELECT语句一起使用。 GROUP BY语句在SELECT语句中跟随WHERE子句,并在ORDER BY子句之前。GROUP BY语句与聚合函数一起使用。
语法
SELECT column FROM table_name WHERE conditions GROUP BY column ORDER BY column
假设有一个表:PRODUCT_MAST,它的结构和数据记录如下所示 -
| PRODUCT | COMPANY | QTY | RATE | COST |
|---|---|---|---|---|
| Item1 | Com1 | 2 | 10 | 20 |
| Item2 | Com2 | 3 | 25 | 75 |
| Item3 | Com1 | 2 | 30 | 60 |
| Item4 | Com3 | 5 | 10 | 50 |
| Item5 | Com2 | 2 | 20 | 40 |
| Item6 | Cpm1 | 3 | 25 | 75 |
| Item7 | Com1 | 5 | 30 | 150 |
| Item8 | Com1 | 3 | 10 | 30 |
| Item9 | Com2 | 2 | 25 | 50 |
| Item10 | Com3 | 4 | 30 | 120 |
示例
SELECT COMPANY, COUNT(*) FROM PRODUCT_MAST GROUP BY COMPANY;
执行上面语句,得到结果如下 -
Com1 5 Com2 3 Com3 2
2. HAVING子句
HAVING子句用于指定分组或聚合的搜索条件。- 需要在
GROUP BY子句中使用,如果没有使用GROUP BY子句,那么可以像使用WHERE子句一样使用HAVING函数。
语法:
SELECT column1, column2 FROM table_name WHERE conditions GROUP BY column1, column2 HAVING conditions ORDER BY column1, column2;
示例
SELECT COMPANY, COUNT(*) FROM PRODUCT_MAST GROUP BY COMPANY HAVING COUNT(*)>2;
执行上面语句,得到结果如下 -
Com1 5 Com2 3
3.ORDER BY子句
ORDER BY子句按升序或降序对结果集进行排序。- 它默认按升序对记录进行排序。
DESC关键字用于按降序对记录进行排序。
语法:
SELECT column1, column2 FROM table_name WHERE condition ORDER BY column1, column2... ASC|DESC;
其中,
ASC:用于按表达式按升序对结果集进行排序。DESC:它按表达式按降序对结果集进行排序。
示例:按升序排序结果
假设有一个CUSTOMER表,它的结构和数据记录如下 -
| CUSTOMER_ID | NAME | ADDRESS |
|---|---|---|
| 12 | Kathrin | US |
| 23 | David | Bangkok |
| 34 | Alina | Dubai |
| 45 | John | UK |
| 56 | Harry | US |
执行以下SQL语句:
SELECT * FROM CUSTOMER ORDER BY NAME;
得到以下结果 -
| CUSTOMER_ID | NAME | ADDRESS |
|---|---|---|
| 34 | Alina | Dubai |
| 23 | David | Bangkok |
| 56 | Harry | US |
| 45 | John | UK |
| 12 | Kathrin | US |
示例:按降序排序结果
基于上面的CUSTOMER表,执行下面SQL语句 -
SELECT * FROM CUSTOMER ORDER BY NAME DESC;
得到以下结果 -
| CUSTOMER_ID | NAME | ADDRESS |
|---|---|---|
| 12 | Kathrin | US |
| 45 | John | UK |
| 56 | Harry | US |
| 23 | David | Bangkok |
| 34 | Alina | Dubai |
SQL聚合函数
SQL聚合函数用于对表的单个列的多行执行计算,它只返回一个值。它还用于汇总数据。
SQL聚合函数的类型,如下图所示 -
接下来,我们一个个地讲解。
1.COUNT函数
COUNT函数用于计算数据库表中的行数,它可以在数字和非数字数据类型上工作。COUNT函数使用COUNT(*)返回指定表中所有行的计数。COUNT(*)包函重复值和NULL值。
语法
COUNT(*) # 或者 COUNT( [ALL|DISTINCT] expression )
假设有一个PRODUCT_MAST表,它的结构和数据如下所示 -
| PRODUCT | COMPANY | QTY | RATE | COST |
|---|---|---|---|---|
| Item1 | Com1 | 2 | 10 | 20 |
| Item2 | Com2 | 3 | 25 | 75 |
| Item3 | Com1 | 2 | 30 | 60 |
| Item4 | Com3 | 5 | 10 | 50 |
| Item5 | Com2 | 2 | 20 | 40 |
| Item6 | Cpm1 | 3 | 25 | 75 |
| Item7 | Com1 | 5 | 30 | 150 |
| Item8 | Com1 | 3 | 10 | 30 |
| Item9 | Com2 | 2 | 25 | 50 |
| Item10 | Com3 | 4 | 30 | 120 |
示例1
SELECT COUNT(*) FROM PRODUCT_MAST;
执行上面语句,得到以下结果 -
10
示例2
SELECT COUNT(*) FROM PRODUCT_MAST; WHERE RATE>=20;
执行上面语句,得到以下结果 -
7
示例3
SELECT COUNT(DISTINCT COMPANY) FROM PRODUCT_MAST;
执行上面语句,得到以下结果 -
3
示例4
SELECT COUNT(DISTINCT COMPANY) FROM PRODUCT_MAST;
执行上面语句,得到以下结果 -
3
示例5
SELECT COMPANY, COUNT(*) FROM PRODUCT_MAST GROUP BY COMPANY;
执行上面语句,得到以下结果 -
Com1 5 Com2 3 Com3 2
示例6
SELECT COMPANY, COUNT(*) FROM PRODUCT_MAST GROUP BY COMPANY HAVING COUNT(*)>2;
执行上面语句,得到以下结果 -
Com1 5 Com2 3
2. SUM函数
Sum函数用于计算所有选定列的总和。它仅适用于数字类型的字段。
语法
SUM() # 或 SUM( [ALL|DISTINCT] expression )
示例1
SELECT SUM(COST) FROM PRODUCT_MAST;
执行上面查询语句,得到以下结果 -
670
示例2
SELECT SUM(COST) FROM PRODUCT_MAST WHERE QTY>3;
执行上面查询语句,得到以下结果 -
320
示例3
SELECT SUM(COST) FROM PRODUCT_MAST WHERE QTY>3 GROUP BY COMPANY;
执行上面查询语句,得到以下结果 -
Com1 150 Com2 170
示例4
SELECT COMPANY, SUM(COST) FROM PRODUCT_MAST GROUP BY COMPANY HAVING SUM(COST)>=170;
执行上面查询语句,得到以下结果 -
Com1 335 Com3 170
3. AVG函数
AVG函数用于计算数值类型的平均值。AVG函数返回所有非Null值的平均值。
语法
AVG() #或 AVG( [ALL|DISTINCT] expression )
示例1
SELECT AVG(COST) FROM PRODUCT_MAST;
执行上面查询语句,得到以下结果 -
67.00
4. MAX函数
MAX函数用于查找某列的最大值,此函数确定列的所有选定值的最大值。
语法
MAX() # 或 MAX( [ALL|DISTINCT] expression )
示例1
SELECT MAX(RATE) FROM PRODUCT_MAST;
执行上面查询语句,得到以下结果 -
30
5. MIN函数
MIN函数用于查找某列的最小值,此函数确定列的所有选定值的最小值。
语法
MIN() # 或 MIN( [ALL|DISTINCT] expression )
示例1
SELECT MIN(RATE) FROM PRODUCT_MAST;
执行上面查询语句,得到以下结果 -
10
SQL连接查询
顾名思义,连接(JOIN)表示要结合一些东西。 在SQL的情况下,连接(JOIN)表示“组合两个或更多表”。
在SQL中,JOIN子句用于组合数据库中两个或多个表的记录。
SQL JOIN的类型
- 内连接 - INNER JOIN
- 左连接 - LEFT JOIN
- 右连接 - RIGHT JOIN
- 全连接 - FULL JOIN
假设有以下几张表,EMPLOYEE表的结构和数据如下所示 -
| EMP_ID | EMP_NAME | CITY | SALARY | AGE |
|---|---|---|---|---|
| 1 | Angelina | Chicago | 200000 | 30 |
| 2 | Robert | Austin | 300000 | 26 |
| 3 | Christian | Denver | 100000 | 42 |
| 4 | Kristen | Washington | 500000 | 29 |
| 5 | Russell | Los angels | 200000 | 36 |
| 6 | Marry | Canada | 600000 | 48 |
PROJECT表的结构和数据如下所示 -
| PROJECT_NO | EMP_ID | DEPARTMENT |
|---|---|---|
| 101 | 1 | Testing |
| 102 | 2 | Development |
| 103 | 3 | Designing |
| 104 | 4 | Development |
1.内连接
在SQL中,只要条件满足,INNER JOIN就会选择两个表中具有匹配值的记录。 它返回条件满足的两个表中所有行的组合。
语法
SELECT table1.column1, table1.column2, table2.column1,.... FROM table1 INNER JOIN table2 ON table1.matching_column = table2.matching_column;
查询语句示例 -
SELECT EMPLOYEE.EMP_NAME, PROJECT.DEPARTMENT FROM EMPLOYEE INNER JOIN PROJECT ON PROJECT.EMP_ID = EMPLOYEE.EMP_ID;
执行上面查询语句,得到以下结果 -
| EMP_NAME | DEPARTMENT |
|---|---|
| Angelina | Testing |
| Robert | Development |
| Christian | Designing |
| Kristen | Development |
2. 左连接 - LEFT JOIN
SQLleft join返回左表中的所有值和右表中的匹配值。如果没有匹配的连接值,则返回NULL。
语法
SELECT table1.column1, table1.column2, table2.column1,.... FROM table1 LEFT JOIN table2 ON table1.matching_column = table2.matching_column;
查询语句示例 -
SELECT EMPLOYEE.EMP_NAME, PROJECT.DEPARTMENT FROM EMPLOYEE LEFT JOIN PROJECT ON PROJECT.EMP_ID = EMPLOYEE.EMP_ID;
执行上面查询语句,得到以下结果 -
| EMP_NAME | DEPARTMENT |
|---|---|
| Angelina | Testing |
| Robert | Development |
| Christian | Designing |
| Kristen | Development |
| Russell | NULL |
| Marry | NULL |
3. 右连接 - RIGHT JOIN
在SQL中,RIGHT JOIN返回右表行中的值和左表中匹配值的所有值。如果两个表中都没有匹配,则返回NULL。
语法
SELECT table1.column1, table1.column2, table2.column1,.... FROM table1 RIGHT JOIN table2 ON table1.matching_column = table2.matching_column;
查询语句示例 -
SELECT EMPLOYEE.EMP_NAME, PROJECT.DEPARTMENT FROM EMPLOYEE RIGHT JOIN PROJECT ON PROJECT.EMP_ID = EMPLOYEE.EMP_ID;
执行上面查询语句,得到以下结果 -
| EMP_NAME | DEPARTMENT |
|---|---|
| Angelina | Testing |
| Robert | Development |
| Christian | Designing |
| Kristen | Development |
4. 全连接 - FULL JOIN
在SQL中,FULL JOIN是左外连接和右外连接组合的结果。 连接表包含两个表中的所有记录。 它将NULL放在未找到的匹配位置。
语法
SELECT table1.column1, table1.column2, table2.column1,.... FROM table1 FULL JOIN table2 ON table1.matching_column = table2.matching_column;
查询语句 -
SELECT EMPLOYEE.EMP_NAME, PROJECT.DEPARTMENT FROM EMPLOYEE FULL JOIN PROJECT ON PROJECT.EMP_ID = EMPLOYEE.EMP_ID;
执行上面查询语句,得到以下结果 -
| EMP_NAME | DEPARTMENT |
|---|---|
| Angelina | Testing |
| Robert | Development |
| Christian | Designing |
| Kristen | Development |
| Russell | NULL |
| Marry | NULL |
SQL集合操作
SQL集合操作用于组合两个或多个SQL SELECT语句。
集合操作的类型
- 联合 - Union
- 联合所有 - UnionAll
- 交集 - Intersect
- 差集 - Minus
联合 - Union
SQL Union操作用于组合两个或多个SQL SELECT查询的结果。
在union操作中,在应用UNION操作的两个表中,所有数据类型和列的数量必须相同。union操作从结果集中删除重复的行。
语法
SELECT column_name FROM table1 UNION SELECT column_name FROM table2;
假设有两个表,第一个表:First的结构和数据如下 -
| ID | NAME |
|---|---|
| 1 | Jack |
| 2 | Harry |
| 3 | Jackson |
第二个表:Second的结构和数据如下 -
| ID | NAME |
|---|---|
| 3 | Jackson |
| 4 | Stephan |
| 5 | David |
Union的SQL查询如下:
SELECT * FROM First UNION SELECT * FROM Second;
执行查询后如下所示:
| ID | NAME |
|---|---|
| 1 | Jack |
| 2 | Harry |
| 3 | Jackson |
| 4 | Stephan |
| 5 | David |
2. 全联合 - Union All
Union All操作等于Union操作。它返回集合但不删除重复和排序数据。
语法:
SELECT column_name FROM table1 UNION ALL SELECT column_name FROM table2;
示例:使用上面的第一个和第二个表。
Union All查询语句如下:
SELECT * FROM First UNION ALL SELECT * FROM Second;
执行查询后结果如下所示:
| ID | NAME |
|---|---|
| 1 | Jack |
| 2 | Harry |
| 3 | Jackson |
| 3 | Jackson |
| 4 | Stephan |
| 5 | David |
3. 相交
它用于组合两个SELECT语句。 相交(Intersect)操作从两个SELECT语句返回公共行。
在“相交”操作中,数据类型和列的数量必须相同。
它没有重复项,默认情况下按升序排列数据。
语法
SELECT column_name FROM table1 INTERSECT SELECT column_name FROM table2;
示例:
使用上面的First表和Second表。
相交查询语句是:
SELECT * FROM First INTERSECT SELECT * FROM Second;
执行上面查询语句,得到以下结果:
ID NAME ---------------------------------- 3 Jackson
4. 差集
它结合了两个SELECT语句的结果。 差集运算符用于显示第一个查询中存在但第二个查询中不存在的行。
它没有重复项,默认情况下按升序排列数据。
语法:
SELECT column_name FROM table1 MINUS SELECT column_name FROM table2;
示例
使用上面的First表和Second表。
差积查询语句是:
SELECT * FROM First MINUS SELECT * FROM Second;
执行上面查询语句,得到以下结果:
ID NAME ------------------------------------ 1 Jack 2 Harry






