StudyTonight-数据库中文教程-一-

StudyTonight 数据库中文教程(一)

原文:StudyTonight

协议:CC BY-NC-SA 4.0

DBMS

数据库概念

什么是数据?

原文:https://www.studytonight.com/dbms/overview-of-dbms.php

数据只不过是存储或在网络上自由流动的事实和统计数据,一般都是未经加工的原始数据。例如:当你访问任何网站时,他们可能会存储你的 IP 地址,也就是数据,作为回报,他们可能会在你的浏览器中添加一个 cookie,标记你访问了该网站,也就是数据,你的名字,这是数据,你的年龄,这是数据。

数据在被处理时变成信息,变成有意义的东西。比如,根据保存在用户浏览器上的 cookie 数据,如果一个网站可以分析出一般 20-25 岁的男性访问我们的次数更多,那就是从收集的数据中得出的信息。


什么是数据库?

一个数据库是一个相关数据的集合,其组织方式使得数据能够被容易地访问、管理和更新。数据库可以是基于软件的,也可以是基于硬件的,唯一的目的是存储数据。

在早期的计算机时代,数据被收集并存储在磁带上,这些磁带大多是只读的,这意味着一旦数据存储在磁带上,就再也无法读取。它们又慢又笨重,很快计算机科学家意识到他们需要一个更好的解决方案来解决这个问题。

甲骨文公司的联合创始人拉里·埃里森是少数几个意识到需要基于软件的 DBMS 的人之一。


什么是 DBMS?

一个DBMS是一个允许创建、定义和操作数据库的软件,允许用户轻松地存储、处理和分析数据。DBMS 为我们提供了一个界面或工具,来执行各种操作,如创建数据库、在其中存储数据、更新数据、在数据库中创建表等等。

DBMS 还为数据库提供保护和安全。它还在多个用户的情况下保持数据一致性。

以下是目前流行的 DBMS 的一些例子:

  • 关系型数据库
  • 神谕
  • 数据库
  • IBM DB2
  • 一种数据库系统
  • 亚马逊 SimpleDB(基于云)等。

DBMS 的特点

DBMS 具有以下特征:

  1. 存储到表中的数据:数据从不直接存储到数据库中。数据存储在数据库内部创建的表中。DBMS 还允许表之间的关系,这使得数据更有意义和联系。通过查看数据库中创建的所有表,您可以很容易地了解什么类型的数据存储在哪里。
  2. 减少冗余:在现代世界,硬盘非常便宜,但在早期,当硬盘太贵时,数据库中不必要的数据重复是一个大问题。但是 DBMS 遵循标准化,以重复最少的方式划分数据。
  3. 数据一致性:对于实时数据,即不断更新和添加的数据,保持数据的一致性可能会成为一项挑战。但是 DBMS 自己处理这一切。
  4. 支持多用户和并发访问: DBMS 允许多个用户同时对其进行工作(更新、插入、删除数据),并且仍然设法保持数据的一致性。
  5. 查询语言: DBMS 为用户提供了一种简单的查询语言,使用该语言可以在数据库中轻松地获取、插入、删除和更新数据。
  6. 安全性:DBMS 还负责数据的安全性,保护数据免受未经授权的访问。在典型的 DBMS 中,我们可以创建具有不同访问权限的用户帐户,使用这些帐户,我们可以通过限制用户访问来轻松保护我们的数据。
  7. DBMS 支持事务,这使得我们能够在多线程被广泛使用的现实应用中更好地处理和管理数据完整性。

DBMS 的优势

  • 应用程序隔离。
  • 最小的数据复制或数据冗余。
  • 使用查询语言轻松检索数据。
  • 减少开发时间和维护需求。
  • 有了云数据中心,我们现在有了能够存储几乎无限数据的 DBMS。
  • 无缝集成到应用程序编程语言中,这使得向几乎任何应用程序或网站添加数据库变得非常容易。

DBMS 的缺点

  • 这是复杂性
  • 除了开源的 MySQL 之外,获得许可的 DBMSs 通常成本很高。
  • 它们的尺寸很大。


DBMS 的组件

原文:https://www.studytonight.com/dbms/components-of-dbms.php

DBMS 可以分为五大部分,它们是:

  1. 五金器具
  2. 软件
  3. 数据
  4. 程序
  5. 数据库访问语言

让我们有一个简单的图表来看看它们如何组合在一起形成一个 DBMS。

components of database management system


DBMS 组件:硬件

当我们说硬件时,我们指的是计算机、硬盘、数据的输入/输出通道,以及在任何数据成功存储到内存之前涉及的任何其他物理组件。

当我们在个人电脑上运行甲骨文或 MySQL 时,我们电脑的硬盘、我们用来输入所有命令的键盘、我们电脑的内存、只读存储器都变成了 DBMS 硬件的一部分。


DBMS 组件:软件

这是主要组件,因为这是控制一切的程序。DBMS 软件更像是物理数据库的包装器,它为我们提供了一个易于使用的接口来存储、访问和更新数据。

DBMS 软件能够理解数据库访问语言,并将其解释为实际的数据库命令,以便在数据库上执行。


DBMS 组件:数据

数据是 DBMS 设计的资源。创建 DBMS 的动机是存储和利用数据。

在典型的数据库中,用户保存的数据存在并且元数据被存储。

元数据是关于数据的数据。这是由 DBMS 存储的信息,以便更好地理解存储在其中的数据。

例如:当我把我的名字存储在数据库中时,DBMS 会存储这个名字什么时候存储在数据库中,这个名字的大小是多少,是作为相关数据存储到其他一些数据中,还是独立的,所有这些信息都是元数据。


DBMS 组件:过程

过程是指使用 DBMS 的一般说明。这包括设置和安装 DBMS、登录和注销 DBMS 软件、管理数据库、进行备份、生成报告等过程。


DBMS 组件:数据库访问语言

数据库访问语言是一种简单的语言,旨在编写命令来访问、插入、更新和删除存储在任何数据库中的数据。

用户可以用数据库访问语言编写命令,并将其提交给 DBMS 执行,然后由 DBMS 翻译和执行。

用户可以使用访问语言创建新的数据库、表、插入数据、获取存储的数据、更新数据和删除数据。


用户

  • 数据库管理员:数据库管理员或 DBA 是管理完整 DBMS 的人。数据库管理员负责 DBMS 的安全性、可用性、管理许可证密钥、管理用户帐户和访问等。
  • 应用程序员或软件开发人员:该用户组参与开发和设计 DBMS 的各个部分。
  • 最终用户:如今,所有的现代应用程序,无论是网络还是移动,都存储用户数据。你觉得他们是怎么做到的?是的,应用程序的编程方式是收集用户数据,并将数据存储在服务器上运行的 DBMS 中。最终用户是存储、检索、更新和删除数据的人。


理解 DBMS 架构

原文:https://www.studytonight.com/dbms/architecture-of-database.php

DBMS 并不总是直接可供用户和应用程序访问和存储数据。DBMS 可以是集中式的(所有数据存储在一个位置)、分散式的(数据库在不同位置的多个副本)或分层式的,这取决于其体系结构。

1 层 DBMS 架构也是存在的,这就是当数据库直接可供用户使用它来存储数据的时候。一般来说,这种设置用于本地应用程序开发,程序员直接与数据库通信以获得快速响应。

数据库体系结构在逻辑上有两种类型:

  1. 两层 DBMS 体系结构
  2. 三层 DBMS 体系结构

两层 DBMS 体系结构

2 层 DBMS 架构包括用户和 DBMS 之间的应用层,负责将用户的请求传递给 DBMS,然后将 DBMS 的响应发送给用户。

一个被称为 ODBC (开放数据库连接)的应用程序接口提供了一个允许客户端程序调用 DBMS 的应用编程接口。大多数 DBMS 供应商为他们的 DBMS 提供 ODBC 驱动程序。

2-tier dbms architecture

这样的架构为 DBMS 提供了额外的安全性,因为它不会直接暴露给最终用户。此外,还可以通过在应用层添加安全性和身份验证检查来提高安全性。


三层 DBMS 架构

三层 DBMS 架构是 web 应用程序最常用的架构。

3-tier dbms architecture

它是 2 层架构的扩展。在 2 层体系结构中,我们有一个应用层,可以通过编程方式访问它,以便在 DBMS 上执行各种操作。应用程序通常理解数据库访问语言,并处理最终用户对 DBMS 的请求。

在三层体系结构中,添加了一个额外的表示层或图形用户界面层,为最终用户与 DBMS 交互提供了一个图形用户界面。

对于最终用户来说,图形用户界面层是数据库系统,最终用户对应用层和 DBMS 一无所知。

如果你用过 MySQL ,那么你一定见过 PHPMyAdmin ,它是三层 DBMS 架构最好的例子。



DBMS 的数据库模型

原文:https://www.studytonight.com/dbms/database-model.php

数据库模型定义了数据库的逻辑设计和结构,并定义了如何在 DBMS 中存储、访问和更新数据。虽然关系模型是使用最广泛的数据库模型,但也有其他模型:


层次模型

这个数据库模型将数据组织成树状结构,只有一个根,所有其他数据都链接到这个根。层级结构从数据开始,像树一样展开,将子节点添加到父节点。

在这个模型中,子节点只有一个父节点。

这个模型有效地描述了许多现实世界的关系,比如一本书的索引,食谱等等。

在层次模型中,数据被组织成树状结构,两种不同类型的数据之间有一对多的关系,例如,一个部门可以有许多课程,许多教授,当然还有许多学生。

Hierarchical Model of database


网络模型

这是层次模型的扩展。在这个模型中,数据被组织得更像一个图,并且允许有多个父节点。

在这个数据库模型中,随着更多的关系在这个数据库模型中建立,数据更加相关。此外,由于数据更加相关,因此访问数据也更加容易和快速。该数据库模型用于映射多对多数据关系。

在引入关系模型之前,这是最广泛使用的数据库模型。

Network Model of database


实体关系模型

在这个数据库模型中,关系是通过将感兴趣的对象划分为实体并将其特征划分为属性来创建的。

不同的实体使用关系进行关联。

E-R 模型被定义为将关系表示为图形形式,以使不同的利益相关者更容易理解。

这个模型很适合设计数据库,然后可以将数据库转换成关系模型中的表(解释如下)。

举个例子,如果我们要设计一个学校数据库,那么学生将是一个实体,具有属性姓名、年龄、地址等。由于地址一般比较复杂,可以是另一个实体,带有属性街道名称、密码、城市等,它们之间会有关系。

关系也可以是不同的类型。详细了解 E-R 图,点击链接。

E-R Model of database


关系模型

在该模型中,数据被组织在二维中,并且通过存储公共字段来维护关系。

该模型由 E . F Codd 于 1970 年引入,此后一直是应用最广泛的数据库模型,事实上,我们可以说是全世界唯一使用的数据库模型。

关系模型中数据的基本结构是表。与特定类型相关的所有信息都存储在该表的行中。

因此,表在关系模型中也被称为关系

在接下来的教程中,我们将学习如何设计表,将它们规范化以减少数据冗余,以及如何使用结构化查询语言从表中访问数据。

Relational Model of database



DBMS 中 ER 模型的基本概念

原文:https://www.studytonight.com/dbms/er-model-concepts.php

正如我们在教程数据库模型中所描述的,实体关系模型是一个用于设计和表示数据之间关系的模型。

主要数据对象被称为实体,它们的细节被定义为属性,其中一些属性很重要,用于标识实体,不同的实体使用关系进行关联。

简而言之,要了解 ER 模型,我们必须了解:

  • 实体和实体集
  • 什么是属性?和属性类型。
  • 关系

让我们举个例子来解释一切。对于一个学校管理软件,我们需要存储学生信息、老师信息、班级各班所教科目等。


ER 模型:实体和实体集

考虑到上面的例子,学生是实体,老师是实体,同样,学科等也是实体。

实体通常是一个现实世界的对象,它具有 DBMS 中的特征和关系。

如果一个学生是一个实体,那么所有学生的完整数据集就是实体集


ER 模型:属性

如果学生是一个实体,那么学生的卷号、学生的姓名、学生的年龄、学生的性别等将是其属性。

一个属性可以有多种类型,下面是在 ER 数据库模型中定义的不同类型的属性:

  1. 简单属性:值为原子且不能进一步分解的属性为简单属性。比如学生的年龄
  2. 复合属性:复合属性由多个简单属性组成。例如,学生的地址将包含、门牌号街道名称密码等。
  3. 派生属性:这些是不存在于整个 DBMS 中的属性,而是使用其他属性派生的。比如某班级学生平均年龄
  4. 单值属性:顾名思义,它们只有一个值。
  5. 多值属性:并且,它们可以有多个值。

急诊室模式:钥匙

如果属性卷号可以在所有学生中唯一地标识一个学生实体,那么属性卷号将被称为一个键。

以下是密钥的类型:

  1. 超级钥匙
  2. 候选关键字
  3. 主关键字

我们已经在数据库键教程中详细介绍了键。


急诊室模型:关系

当一个实体与另一个实体相关时,它们被称为有关系。比如 A 实体与学生实体相关,因为学生在班里学习,所以这是一种关系。

根据所涉及的实体数量,一个被分配给关系。

比如涉及 2 个实体,就说是二元关系,涉及 3 个实体,就说是三元关系,以此类推。

在下一个教程中,我们将学习如何创建 ER 图和使用 ER 图设计数据库。



使用 ER 图

原文:https://www.studytonight.com/dbms/er-diagram.php

ER 图是数据的可视化表示,描述了数据如何相互关联。在 ER 模型中,我们将数据分解为实体、属性和实体之间的设置关系,所有这些都可以用 ER 图直观地表示出来。

例如,在下图中,任何人都可以看到并理解该图想要传达的内容:开发者开发一个网站,而访问者访问一个网站

example of er-diagram


ER 图的组成部分

实体、属性、关系等构成了 ER 图的组成部分,并且有定义的符号和形状来表示它们中的每一个。

让我们看看如何在我们的 ER 图中表示这些。

实体

简单的矩形框代表一个实体。

Entity in ER diagram

实体之间的关系-弱和强

菱形用于建立两个或多个实体之间的关系。

Relationships in ER diagram

任何实体的属性

椭圆用于表示任何实体的属性。它与实体相连。

Attribute in ER diagram

弱实体

弱实体用双矩形框表示。它通常连接到另一个实体。

Weak Entity in ER diagram

任何实体的键属性

为了表示关键属性,椭圆内的属性名称带有下划线。

Key Attribute in ER diagram

任何实体的派生属性

派生属性是基于其他属性派生的属性,例如,年龄可以从出生日期派生。

To represent a derived attribute, another dotted ellipse is created inside the main ellipse.

Derived Attribute in ER diagram

任何实体的多值属性

一个在另一个内部的双椭圆表示可以有多个值的属性。

Multivalued Attribute in ER diagram

任何实体的复合属性

复合属性是属性,它也有属性。

Composite Attribute in ER diagram


ER 图:实体

一个实体可以是任何物体、地点、人或类。在 ER 图中,实体用矩形表示。以一个组织为例——员工、经理、部门、产品以及更多可以被视为组织中的实体。

Entity example ER Diagram

中间的黄色菱形代表一种关系。


ER 图:弱实体

弱实体是依赖于另一个实体的实体。弱实体没有自己的主键属性。双矩形用于表示弱实体。

weak Entity example ER diagram


ER 图:属性

属性描述实体的属性或特征。例如姓名年龄地址等都可以是学生的属性。属性用 eclipse 表示。

attribute example


ER 图:关键属性

键属性代表实体的主要特征。它用于表示主键。带下划线的椭圆表示关键属性。

key attribute example er diagram


ER 图:复合属性

一个属性也可以有自己的属性。这些属性被称为复合属性。

composite attribute example


急诊室图:关系

关系描述了实体之间的关系。关系用钻石或菱形来表示。

relationship example er diagram

实体之间存在三种类型的关系。

  1. 二元关系
  2. 递归关系
  3. 三元关系

ER 图:二元关系

二元关系是指两个实体之间的关系。这进一步分为三种类型。

一对一的关系

这种关系在现实世界中很少见到。

one-to-one relationship example er diagram

上面的例子描述了一个学生只能注册一门课程,并且一门课程也只有一个学生。这不是你在现实关系中通常会看到的。

一对多关系

下面的例子展示了这种关系,这意味着一个学生可以选择多门课程,但一门课程只能有一个学生。听起来很奇怪!事情就是这样。

one-to-many example

多对一关系

它反映了业务规则,即许多实体只能与一个实体相关联。例如,学生只注册一门课程,但一门课程可以有许多学生。

one-to-many example

多对多关系

many-to-many example

上图表示一个学生可以注册多门课程。一门课程可以有 1 个以上的学生注册。


ER 图:递归关系

当一个实体与其自身相关时,它被称为递归关系。

recursive relationship example ER diagram


ER 图:三元关系

三度关系称为三元关系。

三元关系包含三个实体。在这种关系中,我们总是把两个实体放在一起考虑,然后再看第三个。

ternary relationship example ER diagram

例如,在上图中,我们有三个相关的实体,公司产品部门。为了更好地理解这种关系或围绕模型定义规则,我们应该将两个实体联系起来,然后导出第三个实体。

一家公司生产多种产品 /每种产品正好由一家公司生产。

一家公司只在一个运营/每个区都有许多公司在运营。

考虑到以上两个规则或关系,我们看到,虽然完整的关系涉及三个实体,但我们一次要看两个实体。



增强型 ER 模型

原文:https://www.studytonight.com/dbms/generalization-and-specialization.php

随着 20 世纪 80 年代后期数据复杂性的增加,使用传统的 ER 模型进行数据库建模变得越来越困难。因此,对现有的 ER 模型进行了一些改进或增强,使其能够更好地处理复杂的应用程序。

因此,作为增强 er 模型的一部分,与其他改进一起,三个新概念被添加到现有的 ER 模型中,它们是:

  1. 一般化
  2. 专门化
  3. 聚合

让我们了解它们是什么,以及它们为什么被添加到现有的 ER 模型中。


一般化

泛化是一种自下而上的方法,其中两个较低级别的实体组合在一起形成一个较高级别的实体。概括地说,较高层次的实体也可以与其他较低层次的实体相结合,形成更高层次的实体。

它更像超类和子类系统,但唯一的区别是方法,这是自下而上的。因此,实体被组合以形成更一般化的实体,换句话说,子类被组合以形成超类。

generalization in ER model

例如保存当前账户类型实体可以泛化,可以创建一个名称为账户的实体,涵盖两者。


专门化

特殊化与泛化相反。这是一种自上而下的方法,其中一个较高级别的实体可以分解为两个较低级别的实体。在专门化中,一个更高层次的实体可能没有任何更低层次的实体集,这是可能的。

Specialization in ER Model


聚合

聚合是将两个实体之间的关系视为一个单个实体的过程。

aggregration

在上图中,中心球场的关系在一起,是作为一个实体,与另一个实体访客有关系。现在在现实世界中,如果访问者或学生访问辅导中心,他/她永远不会只询问中心或课程,而是会询问两者。



关系 DBMS 的 Codd 规则

原文:https://www.studytonight.com/dbms/codd-rule.php

E.F Codd 是一位计算机科学家,他发明了用于数据库管理的关系模型。基于关系模型,创建了关系数据库。Codd 提出了 13 条规则,通常被称为 Codd 的 12 条规则,以对照他的关系模型测试 DBMS 的概念。Codd 规则实际上定义了一个 DBMS 要成为一个关系 DBMS 所需要的质量。到目前为止,几乎没有任何商业产品遵循所有 13 个 Codd 的规则。即使是甲骨文也只排在 13 名中的 8.5 名之后。Codd 的 12 条规则如下。


规则零

该规则规定,要使一个系统有资格成为关系 DBMS,它必须能够完全通过关系能力来管理数据库。


规则 1:信息规则

所有信息(包括元数据)都将被表示为存储在表格单元格中的数据。行和列必须严格无序。


规则 2:保证访问

每个唯一的数据(原子值)应该可以通过以下方式访问:表名+主键(行)+属性(列)

注意:通过 POINTER 直接访问的能力违反了这个规则。


规则 3:系统处理空值

Null有几个意思,可以表示数据缺失、不适用或没有值。应该始终如一地处理。此外,主键永远不能为空。NULL上的表达式必须为空。


规则 4:活动在线目录

数据库字典(目录)是完整的数据库的结构描述,必须在线存储。目录必须由与数据库其余部分相同的规则管理。目录上应使用与查询数据库相同的查询语言。


规则 5:强大且结构良好的语言

必须有一种结构良好的语言来提供对存储在数据库中的数据的所有访问方式。示例: SQL 等。如果数据库允许在不使用这种语言的情况下访问数据,那么这就是违规。


规则 6:查看更新规则

所有理论上可更新的视图也应该是系统可更新的。


规则 7:关系级操作

每一层关系都必须有插入、删除、更新操作。还应该支持并集、交集、减集等集合运算。


规则 8:物理数据独立性

数据的物理存储对系统来说并不重要。如果说,某个文件支持表被重命名或从一个磁盘移动到另一个磁盘,它应该不会影响应用程序。


规则 9:逻辑数据独立性

如果数据库的逻辑结构(表结构)发生了变化,用户对数据的看法就不应该改变。比方说,如果一个表被分成两个表,一个新的视图应该给出两个表的连接结果。这条规则最难满足。


规则 10:正直独立

数据库应该能够执行自己的完整性,而不是使用其他程序。键和检查约束、触发器等应存储在数据字典中。这也使得 RDBMS 独立于前端。


规则 11:分配独立性

不管数据库在网络中的分布如何,它都应该正常工作。即使数据库在地理上是分布式的,数据是以碎片的形式存储的,最终用户也应该得到一个印象,即它存储在同一个地方。这就奠定了分布式数据库的基础。


规则 12:非子版本规则

如果允许对系统进行低级别访问,则它不应该能够破坏或绕过完整性规则来更改数据。这可以通过某种查找或加密来实现。



基本关系 DBMS 概念

原文:https://www.studytonight.com/dbms/rdbms-concept.php

一个关系 DBMS (RDBMS)是基于 E . F Codd 引入的关系模型的 DBMS。在关系模型中,数据存储在关系(表)中,并以元组(行)的形式表示。

关系 DBMS用于管理关系数据库。关系数据库是一组相互关联的有组织的表的集合,从中可以很容易地访问数据。关系数据库是目前最常用的数据库。


关系 DBMS:什么是表?

在关系数据库模型中,是按行和列组织的数据元素的集合。表格也被认为是关系的方便表示。但是一个表可以有重复的数据行,而真正的关系不能有重复的数据。表是最简单的数据存储形式。下面是一个雇员表的示例。

| 身份 | 名字 | 年龄 | 薪水 |
| one | 圣经》和《古兰经》传统中)亚当(人类第一人的名字 | Thirty-four | Thirteen thousand |
| Two | 亚历克斯 | Twenty-eight | Fifteen thousand |
| three | 斯图亚特 | Twenty | Eighteen thousand |
| four | 罗斯 | forty-two | Nineteen thousand and twenty |


什么是元组?

表中的单个条目称为元组记录。表中的元组代表一组相关数据。比如上面的员工表有 4 个元组/记录/行。

下面是单个记录或元组的示例。

| one | 圣经》和《古兰经》传统中)亚当(人类第一人的名字 | Thirty-four | Thirteen thousand |


什么是属性?

一个表由几个记录(行)组成,每个记录可以分解成几个更小的数据部分,称为属性。以上员工表由四个属性组成,身份证姓名年龄工资

属性域

当在一个关系(表)中定义一个属性时,它被定义为只保存某一类型的值,这就是所谓的属性域

因此,属性名称将保存每个元组的员工姓名。如果我们将员工的地址保存在那里,这将违反关系数据库模型。

| 名字 |
| 圣经》和《古兰经》传统中)亚当(人类第一人的名字 |
| 亚历克斯 |
| 阿姆斯特丹 OC 街斯图尔特- 9/401 号 |
| 罗斯 |


什么是关系模式?

关系模式描述了关系的结构,包括关系的名称(表的名称)、属性及其名称和类型。


什么是关系键?

关系键是一种属性,它可以唯一地标识关系(表)中的特定元组(行)。


关系完整性约束

关系数据库模型中的每一个关系都应该遵守或遵循一些约束才能成为有效的关系,这些约束被称为关系完整性约束

三个主要的完整性约束是:

  1. 关键限制
  2. 领域约束
  3. 引用完整性约束

关键限制

我们将数据存储在表中,以便以后需要时访问。在每个表中,一个或多个属性一起用于从表中获取数据。键约束指定关系(表)中应该有这样的属性(列),可以用来为任何元组(行)提取数据。

对于两个不同的数据行,键属性不应为空值或相同值。

例如,在员工表中,我们可以使用属性ID为每个员工提取数据。ID的任何值都不为空,并且每行都是唯一的,因此它可以是我们的关键属性

领域约束

域约束是指为可以为某个属性存储的值定义的规则。

如上所述,我们无法在姓名一栏中存储员工的地址

同样,手机号码不能超过 10 位数。

参照完整性约束

我们将在后面详细研究这一点。现在记住这个例子,如果我说 Supriya 是我的女朋友,那么一个叫 Supriya 的女孩也应该存在,这样这段关系才会存在。

如果一个表引用了另一个表中的一些数据,那么该表和该数据应该存在,以使引用完整性约束为真。



什么是关系代数?

原文:https://www.studytonight.com/dbms/relational-algebra.php

每个 DBMS 都必须定义一种查询语言,以允许用户访问存储在数据库中的数据。关系代数是一种过程查询语言,用于查询数据库表以不同的方式访问数据。

在关系代数中,输入是一个关系(必须从中访问数据的表),输出也是一个关系(保存用户请求的数据的临时表)。

Introduction to Relational Algebra

关系代数一次对整个表起作用,所以我们不必使用循环等逐个迭代数据的所有行(元组)。我们所要做的就是指定我们需要数据的表名,在一行命令中,关系代数将遍历整个给定的表来为您获取数据。

我们可以使用关系代数执行的主要操作是:

  1. 挑选
  2. 项目
  3. 联盟
  4. 设置不同
  5. 笛卡尔乘积
  6. 重新命名

选择操作(σ)

这用于从满足给定条件的表(关系)中获取行(元组)。

语法: σ<sub>p</sub>(r)

其中,σ代表选择谓词,r是关系的名称(要在其中查找数据的表名),p是介词逻辑,我们在这里指定数据必须满足的条件。在介词逻辑中,可以使用一元二元运算符,如=<>等来指定条件。

我们以上面关系代数导论中指定的 Student 表为例,取年龄大于 17 的学生的数据。

σ<sub>age > 17</sub> (Student)

这将从表学生中获取元组(行),其中年龄将大于 17

您也可以使用、andor等运算符来指定两个条件,例如,

σ<sub>age > 17 and gender = 'Male'</sub> (Student)

这将返回来自表学生的元组(行),其中包含年龄超过 17 岁的男学生的信息。(考虑学生表也有属性Gender。)


项目运营(∏)

项目操作用于仅投影关系的特定属性集。简单来说,如果你只想看到学生表中所有学生的名字,那么你可以使用项目操作。

它将只投影或显示要求的列或属性,还将从列中删除重复的数据。

语法: ∏<sub>A1, A2...</sub>(r)

其中 A1、A2 等是属性名(列名)。

例如,

∏<sub>Name, Age</sub>(Student)

上面的语句将只显示学生表中所有数据行的姓名年龄列。


联合作战(∩)

此操作用于从两个关系(表)或临时关系(另一个操作的结果)中获取数据。

要使该操作起作用,指定的关系(表)应该具有相同数量的属性(列)和相同的属性域。同样,从结果中自动消除重复的元组。

语法: A ∪ B

其中 A 和 B 是关系。

例如,如果我们有两个表 RegularClassExtraClass ,两个表都有一列 student 来保存学生的姓名,那么,

∏<sub>Student</sub>(RegularClass) ∪ ∏<sub>Student</sub>(ExtraClass)

以上操作将给出学生的名字,他们既上常规课又上课外课,消除了重复。


设置差异(-)

此操作用于查找存在于一个关系中而不存在于第二个关系中的数据。这个操作也适用于两个关系,就像 Union 操作一样。

语法: A - B

其中 A 和 B 是关系。

例如,如果我们想找到参加常规课程但不参加额外课程的学生的姓名,那么,我们可以使用以下操作:

∏<sub>Student</sub>(RegularClass) - ∏<sub>Student</sub>(ExtraClass)


笛卡尔乘积

这用于将两个不同关系(表)中的数据组合成一个,并从组合关系中获取数据。

语法: A X B

例如,如果我们想找到上午进行的常规课和课外课的信息,那么,我们可以使用以下操作:

σ<sub>time = 'morning'</sub> (RegularClass X ExtraClass)

为了使上述查询起作用,常规类超类都应该具有属性时间


重命名操作(ρ)

该操作用于重命名任何查询操作的输出关系,该查询操作返回诸如选择、项目等结果。或者简单地重命名关系(表)

语法: ρ(RelationNew, RelationOld)

除了这些常见的操作之外,关系代数还用于连接操作,例如,

  • 自然连接
  • 外部连接
  • θ连接等。


什么是关系演算?

原文:https://www.studytonight.com/dbms/relational-calculus.php

与关系代数相反,关系代数是一种获取数据的过程查询语言,也解释了它是如何完成的,而非过程查询语言中的关系演算没有描述查询将如何工作或者数据将如何被获取。它只关注做什么,而不是如何做。

关系演算有两种形式:

  1. 元组关系演算
  2. 领域关系演算

元组关系演算

在元组关系演算中,我们基于给定的条件过滤元组。

语法: { T | Condition }

在这种形式的关系演算中,我们定义一个元组变量,指定要在其中搜索元组的表(关系)名称,以及一个条件。

我们也可以使用.点运算符指定列名,用元组变量只获取结果中的某个属性(列)。

很多信息,对吧!给它一些时间来适应。

一个元组变量无非就是一个名字,可以是任何东西,一般我们用单个字母表来表示这个,所以我们说T是一个元组变量。

为了指定要在其中查找数据的关系(表)的名称,我们执行以下操作:

Relation(T),其中T是我们的元组变量。

例如,如果我们的桌子是学生,我们会把它作为Student(T)

然后是条件部分,要指定一个适用于某个 particluar 属性(列)的条件,我们可以使用.点变量和元组变量来指定它,就像表学生中一样,如果我们想要获取年龄大于 17 岁的学生的数据,那么,我们可以这样写:

T.age > 17,其中T是我们的元组变量。

综上所述,如果我们想使用元组关系演算从表学生中获取学生的名字,年龄大于 17 ,那么,对于作为我们元组变量的T

T.name | Student(T) AND T.age > 17


领域关系演算

在领域关系演算中,过滤是基于属性的领域而不是基于元组值来完成的。

语法: { c1, c2, c3, ..., cn | F(c1, c2, c3, ... ,cn)}

其中,c1,c2...etc 表示属性(列)的域,F定义了包含取数据条件的公式。

例如,

{< name, age > | ∈ Student ∧ age > 17}

同样,上述查询将返回表学生中 17 岁以上学生的姓名和年龄。



从 ER 模型到关系模型

原文:https://www.studytonight.com/dbms/er-to-relational-model.php

众所周知,ER 模型可以用 ER 图来表示,这是一种很好的设计方式,可以用流程图的形式来表示数据库设计。

使用 ER 模型设计数据库非常方便,方法是创建一个 ER 图,然后将其转换为关系模型来设计您的表。

不是所有的 ER 模型约束和组件都可以直接转换成关系模型,但是可以导出一个近似的模式。

因此,让我们举几个 ER 图的例子,并将其转换为关系模型模式,从而在关系 DBMS 中创建表。


实体变成表格

ER 模型中的实体被改变成表,或者我们可以说对于 ER 模型中的每个实体,在关系模型中创建一个表。

并且实体的属性被转换成表格的列。

并且在 ER 模型中为实体指定的主键将成为关系模型中表的主键。

例如,对于 ER 模型中的下图 ER 图,

ER model to Relational - Entity to Table

关系模型中将创建一个名为学生的表,该表有 4 列,idnameageaddressid将是该表的主键。


关系变成关系表

在 ER 图中,我们使用菱形/菱形来表示两个实体之间的关系。在关系模型中,我们也为 ER 模型关系创建了一个关系表。

在下面的 ER 图中,我们有两个实体老师学生,它们之间有关系。

ER diagram relationship into table in rdbms

如上所述,实体被映射到表,因此我们将为老师创建表,为学生创建表,并将所有属性转换为列。

现在,将为该关系创建一个额外的表,例如 StudentTeacher 或给它取任何您喜欢的名称。该表将保存学生和教师的主键,用一个元组来描述关系,哪个教师教哪个学生。

如果有与此关系相关的附加属性,则它们会成为此表的列,如主题名称。

还必须为所有表设置适当的外键约束。


需要记住的要点

同样,我们可以使用 ER 图生成关系数据库模式。以下是这样做时要记住的一些要点:

  1. 实体被转换为表,所有属性都成为表中的字段(列)。
  2. 实体之间的关系也转换成表,相关实体的主键也作为外键存储在表中。
  3. 主键应该正确设置。
  4. 对于弱实体的任何关系,如果表中包含任何其他实体的主键,则必须定义外键约束。


数据库键简介

原文:https://www.studytonight.com/dbms/database-key.php

键是关系数据库模型中非常重要的一部分。它们用于建立和标识表之间的关系,也用于唯一标识表中的任何记录或数据行。

密钥可以是单个属性或一组属性,其中组合可以充当密钥。

下面的视频涵盖了关系 DBMS 中所有不同的键。

为什么我们需要一把钥匙?

在现实世界的应用程序中,存储数据所需的表的数量是巨大的,不同的表也是相互关联的。

此外,表中存储了大量数据。表通常扩展到存储在其中的成千上万条记录,这些记录没有分类也没有组织。

现在,要从这样的数据集中提取任何特定的记录,您必须应用一些条件,但是如果存在重复的数据,并且每次您试图通过应用某些条件来提取一些数据时,都会得到错误的数据,那该怎么办呢?在你得到正确的数据之前,有多少次试验?

为了避免这一切,被定义为容易识别表中的任何数据行。

让我们用一个简单的例子来理解所有的键。

| 学生 id | 名字 | 电话 | 年龄 |
| one | 阿康 | Nine billion eight hundred and seventy-six million seven hundred and twenty-three thousand four hundred and fifty-two | Seventeen |
| Two | 阿康 | Nine billion nine hundred and ninety-one million one hundred and sixty-five thousand six hundred and seventy-four | Nineteen |
| three | Bkon | Seven billion eight hundred and ninety-eight million seven hundred and fifty-six thousand five hundred and forty-three | Eighteen |
| four | Ckon 先生 | Eight billion nine hundred and eighty-seven million eight hundred and sixty-seven thousand eight hundred and ninety-eight | Nineteen |
| five | Dkon | Nine billion nine hundred and ninety million eighty thousand and eighty | Seventeen |

我们来看一个简单的学生表,有字段student_idnamephoneage


超级钥匙

超级键定义为表内的一组属性,可以唯一标识表内的每条记录。超级密钥是候选密钥的超集。

在上面定义的表中,超级键将包括student_id(student_id, name)phone等。

迷茫?第一个非常简单,因为student_id对于每一行数据都是唯一的,因此它可以用来唯一地标识每一行。

接下来是(student_id, name),现在两个学生的名字可以相同,但是他们的student_id不能相同,因此这个组合也可以是一个键。

同样,每个学生的电话号码都是唯一的,因此phone也可以是一个键。

所以它们都是超级钥匙。


候选关键字

候选关键字被定义为能够唯一标识表中每条记录的最小字段集。它是一个属性或一组属性,可以作为表的主键来唯一标识该表中的每条记录。可以有多个候选键。

在我们的示例中,student_idphone都是表学生的候选键。

  • 候选键不能为空。它的价值应该是独一无二的。
  • 一个表可以有多个候选键。
  • 候选键可以是多个列(属性)的组合。

主关键字

主键是最适合成为任何表的主键的候选键。它是一个可以唯一标识表中每条记录的键。

primary key for a table

对于表学生我们可以将student_id列作为主键。


复合键

由两个或多个唯一标识表中任何记录的属性组成的键称为复合键。但是共同构成复合键的属性不是独立的或单独的键。

composite key for a table

在上图中,我们有一个分数表,它存储了学生在特定科目中的分数。

在该表中student_idsubject_id将一起形成主键,因此它是一个复合键。


辅助或替代键

未被选为主键的候选键被称为辅助键或替代键。


非关键属性

非关键属性是表中的属性或字段,而不是表中的候选关键属性/字段。


非质数属性

非主键属性是除主键属性以外的属性。



数据库的规范化

原文:https://www.studytonight.com/dbms/database-normalization.php

数据库规范化是一种组织数据库中数据的技术。规范化是一种分解表的系统方法,以消除数据冗余(重复)和不良特征,如插入、更新和删除异常。这是一个多步骤的过程,将数据放入表格形式,从关系表中删除重复的数据。

标准化主要用于两个目的,

  • 消除冗余(无用)数据。
  • 确保数据相关性有意义,即数据是逻辑存储的。

下面的视频会给你一个很好的数据库规范化的概述。如果你愿意,你可以跳过视频,因为这个概念在视频下面有详细的介绍。


没有规范化的问题

如果一个表没有适当地规范化,并且有数据冗余,那么它不仅会消耗额外的内存空间,而且会使处理和更新数据库变得困难,而不会面临数据丢失。如果数据库没有规范化,插入、更新和删除异常会非常频繁。为了理解这些异常,让我们举一个学生表的例子。

| 滚装船 | 名字 | 树枝 | 煤斗 | office_tel |
| Four hundred and one | 阿康 | 中学生毕业考试 | 薛汀哲 | Fifty-three thousand three hundred and thirty-seven |
| Four hundred and two | Bkon | 中学生毕业考试 | 薛汀哲 | Fifty-three thousand three hundred and thirty-seven |
| Four hundred and three | Ckon 先生 | 中学生毕业考试 | 薛汀哲 | Fifty-three thousand three hundred and thirty-seven |
| Four hundred and four | Dkon | 中学生毕业考试 | 薛汀哲 | Fifty-three thousand three hundred and thirty-seven |

在上表中,我们有 4 个计算机科学的数据。学生。我们可以看到,对于学院内同一个分支的学生重复branchhod(系主任)和office_tel字段的数据,这就是数据冗余


插入异常

假设对于新的录取,除非学生选择了分支,否则不能插入该学生的数据,否则我们将不得不将分支信息设置为

此外,如果我们必须插入同一分支的 100 名学生的数据,则分支信息将对所有这 100 名学生重复。

这些场景只不过是插入异常


上升异常

如果 X 先生离开学院怎么办?还是不再是计算机科学系的 HOD?在这种情况下,所有的学生记录都必须更新,如果我们误错过了任何记录,这将导致数据不一致。这是上升异常。


删除异常

在我们的学生表中,两个不同的信息保存在一起,学生信息和分支信息。因此,在学年结束时,如果学生记录被删除,我们也会丢失分支信息。这是删除异常。


规范化规则

规范化规则分为以下几种正常形式:

  1. 第一范式
  2. 第二范式
  3. 第三范式
  4. BCNF(中央银行)
  5. 第四范式

第一范式(1NF)

对于第一范式的表格,应遵循以下 4 条规则:

  1. 它应该只有单(原子)值属性/列。
  2. 存储在列中的值应该属于同一域
  3. 表中的所有列都应该有唯一的名称。
  4. 数据存储的顺序也无关紧要。

在下一个教程中,我们将详细讨论 第一范式


第二范式(2NF)

对于处于第二范式的表,

  1. 应该是第一范式。
  2. 而且,它不应该有部分依赖。

要了解什么是部分依赖,以及如何将表规范化为第二范式,请跳转到 第二范式 教程。


第三范式(3NF)

当一个表处于第三范式时,

  1. 它是第二范式。
  2. 而且,它没有传递依赖。

这里是 第三范式 教程。但是我们建议你先学习第二范式,然后转向第三范式。


博伊斯和柯德范式(BCNF)

Boyce 和 Codd 范式是第三范式的更高版本。此表单处理 3NF 无法处理的特定类型的异常。没有多个重叠候选关键字的 3NF 表被称为在 BCNF。一张桌子要放在 BCNF,必须满足以下条件:

  • r 必须是第三范式
  • 并且,对于每个函数依赖(X → Y),X 应该是一个超级键。

要通过一个非常容易理解的例子详细了解 BCNF,请前往 博耶-科德范式 教程。


第四范式(4NF)

当一个表处于第四范式时,

  1. 这是在博伊斯-科德范式。
  2. 而且,它没有多值依赖。

这里是 第四范式 教程。但是我们建议你在进入第四范式之前先了解其他范式。



什么是第一范式(1NF)?

原文:https://www.studytonight.com/dbms/first-normal-form.php

在本教程中,我们将学习第一(第一)范式,它更像规范化过程的第一步。第一范式期望您以这样一种方式设计您的表,即它可以很容易地扩展,并且在需要时更容易从中检索数据。

在上一个教程中,我们学习并理解了数据冗余或重复如何导致插入、删除和更新异常等几个问题,以及归一化如何减少数据冗余并使数据更有意义。

如果数据库中的表甚至不是第一范式,则认为数据库设计不良


第一范式规则

第一种范式要求您在设计数据库时遵循一些简单的规则,它们是:

规则 1:单值属性

表中的每一列都应该是单值的,这意味着它们不应该包含多个值。稍后我们将通过一个例子来解释这一点,现在让我们看看其他规则。


规则 2:属性域不应该改变

这更像是一个“常识”规则。在每一列中,存储的值必须是相同的类型。

例如:如果你有一栏dob来保存一组人的出生日期,那么你不能或者不可以将其中一些人的“姓名”和其他人的“出生日期”一起保存在该栏中。它应该只保存所有记录/行的“出生日期”。


规则 3:属性/列的唯一名称

此规则要求表中的每一列都应有唯一的名称。这是为了避免在检索数据或对存储的数据执行任何其他操作时出现混乱。

如果一个或多个列有相同的名称,那么 DBMS 将会混乱。


规则 4:秩序不重要

这条规则说,您在表中存储数据的顺序并不重要。


举个例子

虽然所有的规则都是不言自明的,但让我们举一个例子,我们将创建一个表来存储学生数据,其中将有学生的学号、他们的姓名和他们选择的科目名称。

这是我们的表格,其中添加了一些示例数据。

| 滚动 _ 否 | 名字 | 科目 |
| One hundred and one | 阿康 | 操作系统,CN |
| One hundred and three | Ckon 先生 | 爪哇 |
| One hundred and two | Bkon | C,C++ |

我们的表已经满足了 4 个规则中的 3 个,因为我们所有的列名都是唯一的,我们已经按照我们想要的顺序存储了数据,并且没有在列中混合不同类型的数据。

但是在我们表中的 3 个不同的学生中,有 2 个选择了不止一个科目。我们将主题名称存储在一个单独的列中。但是根据第一范式,每一列必须包含原子值。

如何解决这个问题?

这很简单,因为我们所要做的就是将这些值分解成原子值。

这是我们更新的表格,它现在满足第一范式。

| 滚动 _ 否 | 名字 | 科目 |
| One hundred and one | 阿康 | 旧历法 |
| One hundred and one | 阿康 | 通信网络(Communicating Net 的缩写) |
| One hundred and three | Ckon 先生 | 爪哇 |
| One hundred and two | Bkon | C |
| One hundred and two | Bkon | C++ |

通过这样做,虽然一些值被重复,但是subject列的值现在对于每个记录/行都是原子的。

使用第一范式,数据冗余增加,因为多行中将有许多列具有相同的数据,但每行作为一个整体将是唯一的。



什么是第二范式?

原文:https://www.studytonight.com/dbms/second-normal-form.php

对于处于第二范式的表,它必须满足两个条件:

  1. 表格应该是第一范式。
  2. 不应该有部分依赖。

如果你愿意,你可以跳过视频,因为这个概念将在视频下面详细介绍。

什么是部分依赖?别担心。首先让我们了解一下什么是表中的依赖关系


什么是依赖?

我们举一个学生表的例子,表中有student_idnamereg_no(注册号)、branchaddress(学生家庭住址)。

| 学生 id | 名字 | reg_no | 树枝 | 地址 |
| | | | | |
| | | | | |
| | | | | |

在这个表中,student_id是主键,对于每一行都是唯一的,因此我们可以使用student_id从这个表中获取任何一行数据

即使对于学生姓名相同的情况,如果我们知道student_id,我们也可以很容易地获取正确的记录。

| 学生 id | 名字 | reg_no | 树枝 | 地址 |
| Ten | 阿康 | 07-WY | 中学生毕业考试 | 喀拉拉邦 |
| Eleven | 阿康 | 08-WY | 信息技术 | 古吉拉特邦 |

因此,我们可以说一个表的主键是一列或一组列(复合键),它可以唯一地标识表中的每条记录。

我可以用student_id 10 从学生的分支机构名称中询问,我就能得到。同样,如果我用student_id 1011 询问学生姓名,我也会得到。所以我所需要的就是student_id并且每隔一列都依赖于它,或者可以用它来获取。

这就是依赖,我们也称之为功能依赖


什么是部分依赖?

既然我们知道了什么是依赖,我们就能更好地理解什么是部分依赖。

对于像 Student 这样的简单表,像student_id这样的单个列可以唯一识别表中的所有记录。

但这并不总是正确的。现在,让我们扩展我们的示例,看看是否有超过 1 列可以一起充当主键。

让我们为主题创建另一个表,它将有subject_idsubject_name字段,subject_id将是主键。

| 主题 id | 主题名称 |
| one | 爪哇 |
| Two | C++ |
| three | 服务器端编程语言(Professional Hypertext Preprocessor 的缩写) |

现在我们有一个包含学生信息的学生表和另一个存储科目信息的科目表。

让我们创建另一个表格分数,以存储学生在各自科目中获得的分数。我们还将保留教授该科目的老师的名字以及分数。

| 分数 _id | 学生 id | 主题 id | 记号 | 教师 |
| one | Ten | one | Seventy | Java 老师 |
| Two | Ten | Two | Seventy-five | C++老师 |
| three | Eleven | one | Eighty | Java 老师 |

在评分表中,我们保存学生证以了解这些是哪个学生的分数,学科学生证以了解这些分数是哪个学科的。

student_id + subject_id共同构成此表的候选键(了解数据库键,可以是主键

困惑,这个组合怎么可能是主键?

看,如果我让你给我拿student_id 10 的学生分数,你能从这张表中得到吗?不,因为你不知道哪个科目。如果我给你subject_id,你就不知道是哪个学生了。因此我们需要student_id + subject_id来唯一识别任何一行。

但是部分依赖在哪里?

现在如果你看一下分数表,我们有一个列名teacher,它只依赖于主题,对于 Java 是 Java 老师,对于 C++是 C++老师&等等。

正如我们刚才讨论的,这个表的主键是由两列组成的student_id & subject_id,但是老师的名字只取决于科目,因此有了subject_id,与student_id无关。

这就是部分依赖,表中的属性只依赖于主键的一部分,而不依赖于整个键。


如何删除部分依赖?

对此可以有许多不同的解决方案,但我们的目标是从分数表中删除教师的姓名。

最简单的解决方法是从 Score 表中删除列teacher,并将其添加到 Subject 表中。因此,主题表将变成:

| 主题 id | 主题名称 | 教师 |
| one | 爪哇 | Java 老师 |
| Two | C++ | C++老师 |
| three | 服务器端编程语言(Professional Hypertext Preprocessor 的缩写) | Php 老师 |

我们的分数表现在是第二范式,没有部分依赖。

| 分数 _id | 学生 id | 主题 id | 记号 |
| one | Ten | one | Seventy |
| Two | Ten | Two | Seventy-five |
| three | Eleven | one | Eighty |


快速回顾

  1. 对于处于第二范式的表,它应该处于第一范式,并且不应该具有部分依赖关系。
  2. 当对于复合主键,表中的任何属性只依赖于主键的一部分,而不依赖于完整的主键时,就存在部分依赖关系。
  3. 为了移除部分依赖,我们可以划分表,移除导致部分依赖的属性,并将其移动到其他表中,在那里它很适合。


第三范式(3NF)

原文:https://www.studytonight.com/dbms/third-normal-form.php

第三范式是对第二范式的升级。当一个表处于第二范式并且没有传递依赖时,它就处于第三范式。

在继续学习第三范式之前,请查看以下主题,以便更好地理解这一概念:

下面的视频详细介绍了第三范式的概念。

在上一个教程中,我们学习了第二范式,甚至将我们的评分表规范化为第二范式。

所以我们用同样的例子,我们有 3 张表,学生科目分数

学生表

| 学生 id | 名字 | reg_no | 树枝 | 地址 |
| Ten | 阿康 | 07-WY | 中学生毕业考试 | 喀拉拉邦 |
| Eleven | 阿康 | 08-WY | 信息技术 | 古吉拉特邦 |
| Twelve | Bkon | 09-WY | 信息技术 | 拉贾斯坦邦 |

主题表

| 主题 id | 主题名称 | 教师 |
| one | 爪哇 | Java 老师 |
| Two | C++ | C++老师 |
| three | 服务器端编程语言(Professional Hypertext Preprocessor 的缩写) | Php 老师 |

评分表

| 分数 _id | 学生 id | 主题 id | 记号 |
| one | Ten | one | Seventy |
| Two | Ten | Two | Seventy-five |
| three | Eleven | one | Eighty |

在 Score 表中,我们需要存储一些更多的信息,即考试名称和总分,所以让我们在 Score 表中再添加 2 列。

| 分数 _id | 学生 id | 主题 id | 记号 | 考试名称 | 总分数 |
| | | | | | |
| | | | | | |
| | | | | | |


第三范式的要求

对于第三范式的表,

  1. 应该是第二范式。
  2. 它不应该有传递依赖。

什么是传递依赖?

随着exam_nametotal_marks添加到我们的评分表中,它现在保存了更多的数据。我们评分表的主键是一个复合键,也就是说它是由两个属性或列组成→ 学生号+学科号

我们的新栏目exam_name取决于学生和学科。例如,机械工程专业的学生将参加 Workshop 考试,但计算机科学专业的学生不会。有些科目你有实践考试,有些没有。所以我们可以说exam_name既依赖student_id又依赖subject_id

那我们的第二个新栏目total_marks呢?它依赖于我们的 Score 表的主键吗?

嗯,total_marks一栏取决于exam_name,因为考试类型总成绩会变化。例如,实践考试分数较低,而理论考试分数较高。

但是,exam_name只是评分表中的另一列。它不是主键,甚至不是主键的一部分,total_marks依赖于它。

这是传递依赖。当非质数属性依赖于其他非质数属性而不是依赖于质数属性或主键时。


如何移除传递依赖?

同样,解决方案非常简单。从评分表中取出exam_nametotal_marks列,放入考试表中,并在需要的地方使用exam_id

评分表:第三范式

| 分数 _id | 学生 id | 主题 id | 记号 | 考试 id |
| | | | | |
| | | | | |
| | | | | |

新的考试表格

| 考试 id | 考试名称 | 总分数 |
| one | 车间 | Two hundred |
| Two | 电源 | Seventy |
| three | 实践 | Thirty |


移除可传递依赖关系的优势

移除传递依赖的优点是,

  • 减少了数据重复量。
  • 实现了数据完整性。


Boyce-Codd 范式(BCNF)

原文:https://www.studytonight.com/dbms/boyce-codd-normal-form.php

Boyce-Codd 范式或 BCNF 是第三范式的扩展,也称为 3.5 范式。

在继续使用 Boyce-Codd 范式之前,请查看以下主题,以更好地理解数据库规范化概念:

跟随上面的视频,了解 BCNF 的完整解释。或者,如果你愿意,你甚至可以跳过视频,跳到下面的部分,看完整的教程。

在上一个教程中,我们学习了第三范式,也学习了如何从表中移除传递依赖关系,建议你在这个之前学习上一个教程。


BCNF 规则

对于满足 Boyce-Codd 范式的表,它应该满足以下两个条件:

  1. 应该是第三范式
  2. 而且,对于任何依赖项 A → B,A 都应该是超级键

第二点听起来有点棘手,对吧?简单的说就是,对于一个依赖项 A → B,如果 B 是素属性,A 就不能是非素属性


举个例子

下面我们有一个带有student_idsubjectprofessor栏的大学招生表。

| 学生 id | 科目 | 教授 |
| One hundred and one | 爪哇 | P.Java |
| One hundred and one | C++ | 页(page 的缩写)卡片打印处理机(Card Print Processor 的缩写) |
| One hundred and two | 爪哇 | 页(page 的缩写)Java2 |
| One hundred and three | C# | P.查什 |
| One hundred and four | 爪哇 | P.Java |

如您所见,我们还向表中添加了一些示例数据。

在上表中:

  • 一个学生可以注册多门课程。例如,学号为学号为 101 的学生选择了科目——Java&c++
  • 每个科目都有一名教授分配给学生。
  • 而且,可以有多位教授教一门课程,就像我们教 Java 一样。

你认为主键应该是什么?

嗯,在上面的表中student_id, subject一起组成了主键,因为使用student_idsubject,我们可以找到表的所有列。

这里需要注意的更重要的一点是,一个教授只教一门学科,但是一门学科可能有两个不同的教授。

因此这里subjectprofessor之间有一个依存关系,subject取决于教授的名字。

该表满足第一范式,因为所有值都是原子的,列名是唯一的,并且存储在特定列中的所有值都属于同一域。

该表也满足第二范式,因为它们没有部分依赖

并且,不存在传递依赖,因此该表也满足第三范式

但是这个表不在 Boyce-Codd 范式中。


为什么这张桌子不在 BCNF?

在上表中,student_id, subject构成主键,表示subject列是一个主属性

但是,还有一个依赖,professorsubject

subject是质数属性,professor非质数属性,这是 BCNF 不允许的。


如何让 BCNF 满意?

为了让这个关系(表)满足 BCNF,我们将这个表分解成两个表,学生表和教授表。

下面是这两张表的结构。

学生表

| 学生 id | p_id |
| One hundred and one | one |
| One hundred and one | Two |
| 等等... |

并且,教授表

| p_id | 教授 | 科目 |
| one | P.Java | 爪哇 |
| Two | 页(page 的缩写)卡片打印处理机(Card Print Processor 的缩写) | C++ |
| 等等... |

现在,这个关系满足 Boyce-Codd 范式。在下一个教程中,我们将学习第四范式


更一般的解释

在下图中,我们试图用关系来解释 BCNF。

BCNF Normal Form



第四范式(4NF)

原文:https://www.studytonight.com/dbms/fourth-normal-form.php

当任意关系中出现多值依赖时,第四范式出现。在本教程中,我们将学习多值依赖,如何删除它,以及如何使任何表满足第四范式。

跟随上面的视频,了解第四范式的完整解释。或者,如果你愿意,你甚至可以跳过视频,跳到下面的部分,看完整的教程。

在上一个教程中,我们学习了 boyce-codd 范式 ,建议大家在这一个之前跟着上一个教程学习。


第四范式的规则

对于满足第四范式的表,它应该满足以下两个条件:

  1. 应该是 Boyce-Codd 范式
  2. 并且,表中不应该有任何多值依赖

让我们在下一节中尝试理解什么是多值依赖。


什么是多值依赖?

如果下列条件成立,则称一个表具有多值相关性,

  1. 对于一个依赖项 A → B,如果对于单个值 A,存在多个值 B,那么表可能存在多值依赖。
  2. 此外,一个表应该至少有 3 列才能具有多值依赖关系。
  3. 并且,对于一个关系R(A,B,C),如果 A 和 B 之间存在多值依赖,那么 B 和 C 应该是相互独立的。

如果所有这些条件对于任何关系(表)都成立,则称其具有多值依赖性。


举个例子

下面我们有一个带有s_idcoursehobby栏的大学招生表。

| s_id | 课程 | 业余爱好 |
| one | 科学 | 板球 |
| one | 数学 | 曲棍球 |
| Two | C# | 板球 |
| Two | 服务器端编程语言(Professional Hypertext Preprocessor 的缩写) | 曲棍球 |

从上表可以看到,1 的s_idT1 的学生选择了两门课程理科数学,有两个爱好板球曲棍球

你一定在想这会导致什么问题,对吧?

好的,学生的两个记录加上s_id,会产生两个以上的记录,如下图所示,因为一个学生有两个爱好,因此连同这两个课程,这些爱好应该被指定。

**| s_id | 课程 | 业余爱好 |
| one | 科学 | 板球 |
| one | 数学 | 曲棍球 |
| one | 科学 | 曲棍球 |
| one | 数学 | 板球 |

并且,在上表中coursehobby列之间没有关系。他们彼此独立。

因此存在多值依赖,这导致不必要的数据重复和其他异常。


如何满足第四范式?

为了使上述关系满足第四范式,我们可以将表分解为两个表。

课程选择表

| s_id | 课程 |
| one | 科学 |
| one | 数学 |
| Two | C# |
| Two | 服务器端编程语言(Professional Hypertext Preprocessor 的缩写) |

并且,爱好表

| s_id | 业余爱好 |
| one | 板球 |
| one | 曲棍球 |
| Two | 板球 |
| Two | 曲棍球 |

现在这个关系满足第四范式。

表也可以有函数依赖和多值依赖。在这种情况下,函数依赖列被移动到单独的表中,多值依赖列被移动到单独的表中。

如果您仔细设计数据库,就可以轻松避免这些问题。



第五范式(5NF)

原文:https://www.studytonight.com/dbms/fifth-normal-form.php

数据库规范化中的第五范式在现实生活的数据库设计中一般不会实现。但是你应该知道它是什么。

让我们涵盖第五范式的概念。在下面的视频中,我们已经详细解释过了。



基本 SQL

SQL 入门

原文:https://www.studytonight.com/dbms/introduction-to-sql.php

结构查询语言是一种数据库查询语言,用于在关系数据库中存储和管理数据。SQL 是 E . F Codd 的关系数据库模型引入的第一种商业语言。如今几乎所有的关系 DBMS(MySql、Oracle、Infomix、Sybase、MS Access)都使用 SQL 作为标准的数据库查询语言。SQL 用于在关系 DBMS 中执行所有类型的数据操作。


SQL 命令

SQL 定义了以下方法来操作存储在关系 DBMS 中的数据。


数据定义语言

这包括对表结构的更改,如创建表、更改表、删除表等。

所有 DDL 命令都是自动提交的。这意味着它会将所有更改永久保存在数据库中。

| 命令 | 描述 |
| 创造 | 创建新表或数据库 |
| 改变 | 用于变更 |
| 缩短 | 从表中删除数据 |
| 滴 | 放下桌子 |
| 重新命名 | 重命名表 |


数据操作语言

DML 命令用于操作存储在表中的数据,而不是表本身。

DML 命令不是自动提交的。这意味着对数据库的更改不是永久性的,它们可以回滚。

| 命令 | 描述 |
| 插入 | 插入新行 |
| 更新 | 更新现有行 |
| 删除 | 删除一行 |
| 合并 | 合并两行或两个表 |


事务控制语言

这些命令用于检查其他命令及其对数据库的影响。这些命令可以通过将数据回滚到原始状态来取消其他命令所做的更改。它也可以使任何暂时的改变永久化。

| 命令 | 描述 |
| 犯罪 | 永久保存 |
| 反转 | 撤消更改 |
| 保存点 | 暂时保存 |


数据控制语言

数据控制语言是向任何数据库用户授予和收回权限的命令。

| 命令 | 描述 |
| 同意 | 授予权利许可 |
| 取消 | 收回许可。 |


DQL:数据查询语言

数据查询语言用于根据我们可以轻松应用的条件从表中获取数据。

| 命令 | 描述 |
| 挑选 | 从一个或多个表中检索记录 |



SQL:CREATE命令

原文:https://www.studytonight.com/dbms/create-query.php

create 是一个 DDL SQL 命令,用于在关系 DBMS 中创建表或数据库。


创建数据库

要在关系 DBMS 中创建数据库,使用创建命令。以下是语法,

CREATE DATABASE <DB_NAME>;

创建数据库的示例

CREATE DATABASE Test;

上面的命令将创建一个名为 Test 的数据库,它将是一个没有任何表的空模式。

要在这个新创建的数据库中创建表,我们可以再次使用CREATE命令。


创建表格

CREATE命令也可以用来创建表格。现在,当我们创建一个表时,我们也必须指定表的列的细节。我们可以在CREATE命令本身中指定各列的名称数据类型

以下是语法,

CREATE TABLE <TABLE_NAME>
(
    column_name1 datatype1,
    column_name2 datatype2,
    column_name3 datatype3,
    column_name4 datatype4
);

create table 命令将告诉数据库系统用给定的表名和列信息创建一个新表。


创建表格的示例

CREATE TABLE Student(
    student_id INT, 
    name VARCHAR(100), 
    age INT);

上述命令将在当前数据库中创建一个名为 Student 的新表,该表有 3 列,即student_idnameage。其中student_id列将仅存储整数,name将最多存储 100 个字符,age将再次仅存储整数值。

如果您当前没有登录到要在其中创建表的数据库,那么您也可以使用点运算符.将数据库名称和表名称一起添加

例如,如果我们有一个名为 Test 的数据库,并且我们想在其中创建一个表 Student ,那么我们可以使用以下查询来实现:

CREATE TABLE Test.Student(
    student_id INT, 
    name VARCHAR(100), 
    age INT);

表列最常用的数据类型

这里我们列出了一些最常用于表中列的数据类型。

| 数据类型 | 使用 |
| (同 Internationalorganizations)国际组织 | 用于存储整数值的列。 |
| 漂浮物 | 用于存储浮点值的列。 |
| 两倍 | 用于存储浮点值的列。 |
| 可变长字符串 | 用于存储字符和整数的列,基本上是字符串。 |
| 茶 | 用于存储字符值(单个字符)的列。 |
| 日期 | 用于存储日期值的列。 |
| 文本 | 用于存储通常很长的文本的列。例如,如果您创建了一个表格来存储社交网站的个人资料信息,那么对于“关于我”部分,您可以有一个类型为TEXT的列。 |



SQL: ALTER命令

原文:https://www.studytonight.com/dbms/alter-query.php

alter命令用于改变表格结构,如:

  • 向现有表中添加列
  • 重命名任何现有列
  • 更改任何列的数据类型或修改其大小。
  • 从表中删除一列。

ALTER命令:添加新列

使用ALTER命令,我们可以向任何现有的表中添加一列。以下是语法,

ALTER TABLE table_name ADD(
    column_name datatype);

这里有一个例子,

ALTER TABLE student ADD(
    address VARCHAR(200)
);

上面的命令将在表学生中添加一个新的列address,该列将保存类型为varchar的数据,该数据除了字符串之外什么都没有,长度为 200。


ALTER命令:添加多个新列

使用ALTER命令,我们甚至可以向任何现有的表中添加多个新列。以下是语法,

ALTER TABLE table_name ADD(
    column_name1 datatype1, 
    column-name2 datatype2, 
    column-name3 datatype3);

这里有一个例子,

ALTER TABLE student ADD(
    father_name VARCHAR(60), 
    mother_name VARCHAR(60), 
    dob DATE); 

上述命令将为学生表添加三个新列


ALTER命令:用默认值添加列

ALTER命令也可以使用默认值向现有表中添加新列。当列中没有插入值时,使用默认值。以下是语法,

ALTER TABLE table_name ADD(
    column-name1 datatype1 DEFAULT some_value
);

这里有一个例子,

ALTER TABLE student ADD(
    dob DATE DEFAULT '01-Jan-99'
);

上述命令将在表格学生中添加一个预设默认值的新列。


ALTER命令:修改现有列

ALTER命令也可用于修改任何现有列的数据类型。以下是语法,

ALTER TABLE table_name modify(
    column_name datatype
);

这里有一个例子,

ALTER TABLE student MODIFY(
    address varchar(300)); 

还记得我们在开头加了一个新栏目address吗?上述命令将修改学生表的address列,现在最多可容纳 300 个字符。


ALTER命令:重命名列

使用ALTER命令可以重命名现有列。以下是语法,

ALTER TABLE table_name RENAME 
    old_column_name TO new_column_name;

这里有一个例子,

ALTER TABLE student RENAME 
    address TO location; 

以上命令将address列重命名为location


ALTER命令:放下一列

ALTER命令也可用于删除或删除列。以下是语法,

ALTER TABLE table_name DROP(
    column_name);

这里有一个例子,

ALTER TABLE student DROP(
    address); 

上述命令将从表学生中删除address列。



截断、删除或重命名表

原文:https://www.studytonight.com/dbms/truncate-drop-rename-query.php

在本教程中,我们将学习用于重新定义表的各种 DDL 命令。

TRUNCATE命令

TRUNCATE命令从表中删除所有记录。但是这个命令不会破坏表的结构。当我们对一个表使用TRUNCATE命令时,它的(自动递增)主键也被初始化。下面是它的语法,

TRUNCATE TABLE table_name

这是一个解释它的例子,

TRUNCATE TABLE student;

以上查询将删除表学生中的所有记录。

在 DML 命令中,我们将研究DELETE命令,该命令也或多或少与TRUNCATE命令相同。我们还将在该教程中了解两者之间的区别。


DROP命令

DROP命令从数据库中完全删除一个表。该命令还将破坏表结构和存储在其中的数据。下面是它的语法,

DROP TABLE table_name

这是一个解释它的例子,

DROP TABLE student;

以上查询将完全删除学生表。它也可以用于数据库,删除整个数据库。例如,要删除数据库,

DROP DATABASE Test;

上述查询将从系统中删除名为 Test 的数据库。


RENAME查询

RENAME命令用于为任何现有表设置新名称。以下是语法,

RENAME TABLE old_table_name to new_table_name

下面是一个解释它的例子。

RENAME TABLE student to students_info;

上面的查询会将表学生重命名为学生 _ 信息



使用 SQL INSERT命令

原文:https://www.studytonight.com/dbms/dml-command.php

数据操作语言语句用于管理数据库中的数据。DML 命令不是自动提交的。这意味着 DML 命令所做的更改对数据库来说不是永久的,可以回滚。

说到 Insert 命令,每当我们在 Twitter 上发布一条 tweet 时,文本都会存储在某个表中,当我们发布一条新的 Tweet 时,会在该表中插入一条新记录。


INSERT命令

Insert 命令用于将数据插入表中。以下是它的一般语法,

INSERT INTO table_name VALUES(data1, data2, ...)

让我们看一个例子,

考虑一个表格学生,包含以下字段。

| s_id | 名字 | 年龄 |

INSERT INTO student VALUES(101, 'Adam', 15);

以上命令将在学生表中插入一条新记录。

| s_id | 名字 | 年龄 |
| One hundred and one | 圣经》和《古兰经》传统中)亚当(人类第一人的名字 | Fifteen |


仅在特定列中插入值

我们可以使用INSERT命令只为一行的某些特定列插入值。我们可以指定列名以及要插入的值,如下所示,

INSERT INTO student(id, name) values(102, 'Alex');

上面的 SQL 查询将只在新插入的记录中插入 id 和名称值。


向列中插入空值

以下两个语句都将把NULL值插入到学生表的年龄列中。

INSERT INTO student(id, name) values(102, 'Alex');

或者,

INSERT INTO Student VALUES(102,'Alex', null);

上面的命令将只插入两个列值,另一列设置为 null。

| S_id | S_Name | 年龄 |
| One hundred and one | 圣经》和《古兰经》传统中)亚当(人类第一人的名字 | Fifteen |
| One hundred and two | 亚历克斯 | |


在列中插入默认值

INSERT INTO Student VALUES(103,'Chris', default)

| S_id | S_Name | 年龄 |
| One hundred and one | 圣经》和《古兰经》传统中)亚当(人类第一人的名字 | Fifteen |
| One hundred and two | 亚历克斯 | |
| One hundred and three | 克莉丝 | Fourteen |

假设我们的选项卡中的age列的默认值为 14。

此外,如果您运行下面的查询,它将在年龄列中插入默认值,无论默认值是什么。

INSERT INTO Student VALUES(103,'Chris')


COMMITROLLBACKSAVEPOINT命令

原文:https://www.studytonight.com/dbms/tcl-command.php

事务控制语言(TCL)命令用于管理数据库中的事务。

在继续使用 TCL 命令之前,请先检查以下主题:

这些用于管理 DML 语句对表中数据所做的更改。它还允许将语句组合成逻辑事务。


COMMIT命令

COMMIT命令用于将任何事务永久保存到数据库中。

当我们使用像INSERTUPDATEDELETE这样的任何 DML 命令时,这些命令所做的更改不是永久的,直到当前会话关闭,这些命令所做的更改才能回滚。

为了避免这种情况,我们使用COMMIT命令将更改标记为永久。

下面是 commit 命令语法,

COMMIT;

ROLLBACK命令

此命令将数据库恢复到上次提交的状态。它还与SAVEPOINT命令一起使用,以跳转到正在进行的事务中的保存点。

如果我们已经使用UPDATE命令对数据库进行了一些更改,并且意识到这些更改不是必需的,那么我们可以使用ROLLBACK命令回滚这些更改,如果它们不是使用COMMIT命令提交的话。

以下是回滚命令语法,

ROLLBACK TO savepoint_name;

SAVEPOINT命令

SAVEPOINT命令用于临时保存事务,以便您可以在需要时回滚到该点。

以下是保存点命令语法,

SAVEPOINT savepoint_name;

简而言之,使用此命令,我们可以在任何表中命名数据的不同状态,然后在需要时使用ROLLBACK命令回滚到该状态。


使用保存点和回滚

下表为

| 编号 | 名字 |
| one | 全面 |
| Two | 圣经》和《古兰经》传统中)亚当(人类第一人的名字 |
| four | 亚历克斯 |

让我们在上表中使用一些 SQL 查询并查看结果。

INSERT INTO class VALUES(5, 'Rahul');

COMMIT;

UPDATE class SET name = 'Abhijit' WHERE id = '5';

SAVEPOINT A;

INSERT INTO class VALUES(6, 'Chris');

SAVEPOINT B;

INSERT INTO class VALUES(7, 'Bravo');

SAVEPOINT C;

SELECT * FROM class;

注: SELECT语句用于显示表中存储的数据。

生成的表看起来像,

| 编号 | 名字 |
| one | 全面 |
| Two | 圣经》和《古兰经》传统中)亚当(人类第一人的名字 |
| four | 亚历克斯 |
| five | 牛宿 |
| six | 克莉丝 |
| seven | 好极了 |

现在让我们使用ROLLBACK命令将数据状态回滚到保存点 B

ROLLBACK TO B;

SELECT * FROM class;

现在我们的表会是这样的,

| 编号 | 名字 |
| one | 全面 |
| Two | 圣经》和《古兰经》传统中)亚当(人类第一人的名字 |
| four | 亚历克斯 |
| five | 牛宿 |
| six | 克莉丝 |

现在让我们再次使用ROLLBACK命令将数据状态回滚到保存点 A

ROLLBACK TO A;

SELECT * FROM class;

现在桌子看起来像,

| 编号 | 名字 |
| one | 全面 |
| Two | 圣经》和《古兰经》传统中)亚当(人类第一人的名字 |
| four | 亚历克斯 |
| five | 牛宿 |

现在你知道命令COMMITROLLBACKSAVEPOINT是如何工作的了。



使用GRANTREVOKE

原文:https://www.studytonight.com/dbms/dcl-command.php

数据控制语言用于控制数据库中的权限。要在数据库中执行任何操作,例如创建表、序列或视图,用户需要特权。特权有两种类型,

  • 系统:这包括创建会话、表等的权限以及所有其他类型的系统权限。
  • 对象:这包括对任何命令或查询的权限,以对数据库表执行任何操作。

在 DCL 中,我们有两个命令,

  • GRANT:用于为数据库提供任何用户访问权限或其他特权。
  • REVOKE:用于收回任何用户的权限。

允许用户创建会话

当我们在 SQL 中创建用户时,甚至不允许登录和创建会话,除非向用户授予适当的权限/特权。

以下命令可用于授予会话创建权限。

GRANT CREATE SESSION TO username;

允许用户创建表

为了允许用户在数据库中创建表,我们可以使用下面的命令,

GRANT CREATE TABLE TO username;

为用户提供表空间来存储表

允许用户创建表并不足以开始在该表中存储数据。我们还必须为用户提供特权,以便为他们的表和数据使用可用的表空间。

ALTER USER username QUOTA UNLIMITED ON SYSTEM;

上面的命令将改变用户的详细信息,并提供对系统上无限表空间的访问。

注意:一般情况下,管理员用户是没有限额的。


授予用户所有权限

sysdba是一组特权,其中包含所有权限。因此,如果我们想向任何用户提供所有权限,我们可以简单地授予他们sysdba权限。

GRANT sysdba TO username

授予创建任何表的权限

有时,用户被限制使用为系统表保留的名称创建来表。但是我们可以使用下面的命令授予用户创建任何表的权限,

GRANT CREATE ANY TABLE TO username

授予删除任何表的权限

如标题所示,如果您想允许用户从数据库中删除任何表,那么将此权限授予用户,

GRANT DROP ANY TABLE TO username

收回权限

而且,如果你想收回任何用户的特权,使用REVOKE命令。

REVOKE CREATE TABLE FROM username


使用WHERE子句

原文:https://www.studytonight.com/dbms/where-clause.php

WHERE子句用于在从表中检索、更新或删除数据时指定/应用任何条件。该子句主要用于SELECTUPDATEDELETE查询。

当我们使用WHERE子句指定一个条件时,查询只对那些WHERE子句指定的条件为真的记录执行。


WHERE子句的语法

以下是如何将WHERE子句与DELETE语句或任何其他语句一起使用,

DELETE FROM table_name WHERE [condition];

WHERE子句用于任何 SQL 查询的末尾,以指定执行条件。


举个例子

考虑一张桌子学生

| s_id | 名字 | 年龄 | 地址 |
| One hundred and one | 圣经》和《古兰经》传统中)亚当(人类第一人的名字 | Fifteen | 金奈 |
| One hundred and two | 亚历克斯 | Eighteen | 德里 |
| One hundred and three | 全面 | Seventeen | [军]爆破筒 |
| One hundred and four | 鸭子!鸭子 | Twenty-two | 孟买 |

现在我们将使用SELECT语句根据一个条件显示表中的数据,我们将使用WHERE子句将该条件添加到我们的SELECT查询中。

让我们编写一个简单的 SQL 查询来显示学生的记录,其中s_id为 101。

SELECT s_id, 
    name, 
    age, 
    address 
    FROM student WHERE s_id = 101;

以下是上述查询的结果。

| s_id | 名字 | 年龄 | 地址 |
| One hundred and one | 圣经》和《古兰经》传统中)亚当(人类第一人的名字 | Fifteen | 无聊死了 |


对文本字段应用条件

在上面的例子中,我们已经对整数值字段应用了一个条件,但是如果我们想对name字段应用该条件呢。在这种情况下,我们必须用单引号' '将值括起来。有些数据库甚至接受双引号,但所有数据库都接受单引号。

SELECT s_id, 
    name, 
    age, 
    address 
    FROM student WHERE name = 'Adam';

以下是上述查询的结果。

| s_id | 名字 | 年龄 | 地址 |
| One hundred and one | 圣经》和《古兰经》传统中)亚当(人类第一人的名字 | Fifteen | 无聊死了 |


WHERE条款条件的操作符

以下是在指定WHERE子句条件时可以使用的运算符列表。

| 操作员 | 描述 |
| = | 等于 |
| != | 不等于 |
| < | 不到 |
| > | 大于 |
| <= | 小于或等于 |
| >= | 大于或等于 |
| BETWEEN | 在指定的值范围之间 |
| LIKE | 这用于在值中搜索模式。 |
| IN | 在给定的一组值中 |



SQL SELECT查询

原文:https://www.studytonight.com/dbms/select-query.php

SELECT查询用于从表中检索数据。它是最常用的 SQL 查询。我们可以通过使用WHERE子句指定条件来检索完整的表数据或部分表数据。


SELECT查询的语法

SELECT查询用于重新定时表中的记录。我们可以在结果集中指定我们想要的列的名称。

SELECT 
    column_name1, 
    column_name2, 
    column_name3, 
    ...
    column_nameN 
    FROM table_name;

举个例子

考虑以下学生表,

| s_id | 名字 | 年龄 | 地址 |
| One hundred and one | 圣经》和《古兰经》传统中)亚当(人类第一人的名字 | Fifteen | 金奈 |
| One hundred and two | 亚历克斯 | Eighteen | 德里 |
| One hundred and three | 全面 | Seventeen | [军]爆破筒 |
| One hundred and four | 鸭子!鸭子 | Twenty-two | 孟买 |

SELECT s_id, name, age FROM student;

以上查询将获取学生表的s_idnameage列的信息并显示出来,

| s_id | 名字 | 年龄 |
| One hundred and one | 圣经》和《古兰经》传统中)亚当(人类第一人的名字 | Fifteen |
| One hundred and two | 亚历克斯 | Eighteen |
| One hundred and three | 全面 | Seventeen |
| One hundred and four | 鸭子!鸭子 | Twenty-two |

如您所见,address列的数据不存在,因为我们没有在SELECT查询中指定它。


从表中选择所有记录

一个特殊的字符星号 *用于处理查询中的所有数据(属于所有列)。SELECT语句使用*字符从表中检索所有列的所有记录。

SELECT * FROM student;

上面的查询会显示学生表的所有记录,也就是说会显示该表的完整数据集。

| s_id | 名字 | 年龄 | 地址 |
| One hundred and one | 圣经》和《古兰经》传统中)亚当(人类第一人的名字 | Fifteen | 金奈 |
| One hundred and two | 亚历克斯 | Eighteen | 德里 |
| One hundred and three | 全面 | Seventeen | [军]爆破筒 |
| One hundred and four | 鸭子!鸭子 | Twenty-two | 孟买 |


根据条件选择特定记录

我们可以使用 WHERE子句来设置一个条件,

SELECT * FROM student WHERE name = 'Abhi';

上面的查询将返回以下结果,

| One hundred and three | 全面 | Seventeen | 罗塔克 |


使用SELECT查询执行简单计算

考虑以下员工表。

| 纺织品出口企业代码 | 名字 | 年龄 | 薪水 |
| One hundred and one | 圣经》和《古兰经》传统中)亚当(人类第一人的名字 | Twenty-six | Five thousand |
| One hundred and two | 里奇 | forty-two | Eight thousand |
| One hundred and three | 全面 | Twenty-five | ten thousand |
| One hundred and four | 洛汗 | Twenty-two | Five thousand |

这里是我们的SELECT查询,

SELECT eid, name, salary+3000  FROM employee;

上述命令将在结果中显示一个新的列,将 3000 添加到员工的现有工资中。

| 纺织品出口企业代码 | 名字 | 工资+3000 |
| One hundred and one | 圣经》和《古兰经》传统中)亚当(人类第一人的名字 | Eight thousand |
| One hundred and two | 里奇 | Eleven thousand |
| One hundred and three | 全面 | Thirteen thousand |
| One hundred and four | 洛汗 | Eight thousand |

因此,您也可以使用SELECT查询从表中获取数据,对数据执行简单的数学运算。



SQL LIKE子句

原文:https://www.studytonight.com/dbms/like-clause.php

LIKE子句用于带有WHERE子句的 SQL 查询中的条件。LIKE子句使用通配符运算符将数据与表达式进行比较,以匹配条件中给出的模式。


通配符运算符

LIKE子句中使用了两个通配符运算符。

  • 百分号% :代表零、一个或多个字符。
  • 下划线符号_ :仅代表一个字符。

LIKE子句示例

考虑以下学生表。

| s_id | s_Name | 年龄 |
| One hundred and one | 圣经》和《古兰经》传统中)亚当(人类第一人的名字 | Fifteen |
| One hundred and two | 亚历克斯 | Eighteen |
| One hundred and three | 全面 | Seventeen |

SELECT * FROM Student WHERE s_name LIKE 'A%';

上述查询将返回所有 s_name 以字符“A”开头的记录。

| s_id | s_Name | 年龄 |
| One hundred and one | 圣经》和《古兰经》传统中)亚当(人类第一人的名字 | Fifteen |
| One hundred and two | 亚历克斯 | Eighteen |
| One hundred and three | 全面 | Seventeen |


使用_%

SELECT * FROM Student WHERE s_name LIKE '_d%';

上面的查询将返回所有来自学生表的记录,其中的 s_name 包含“d”作为第二个字符。

| s_id | s_Name | 年龄 |
| One hundred and one | 圣经》和《古兰经》传统中)亚当(人类第一人的名字 | Fifteen |


仅使用%

SELECT * FROM Student WHERE s_name LIKE '%x';

上面的查询将返回所有来自学生表的记录,其中 s_name 包含“x”作为最后一个字符。

| s_id | s_Name | 年龄 |
| One hundred and two | 亚历克斯 | Eighteen |



ORDER BY子句

原文:https://www.studytonight.com/dbms/orderby-clause.php

ORDER BY子句与SELECT语句一起使用,用于按排序顺序排列检索到的数据。默认情况下, Order by 子句按升序对检索到的数据进行排序。为了按降序对数据进行排序DESC关键字与 Order by 子句一起使用。


Order By的语法

SELECT column-list|* FROM table-name ORDER BY ASC | DESC;

使用默认ORDER BY

考虑以下 Emp 表,

| 纺织品出口企业代码 | 名字 | 年龄 | 薪水 |
| Four hundred and one | 安奴 | Twenty-two | Nine thousand |
| Four hundred and two | 谢恩 | Twenty-nine | Eight thousand |
| Four hundred and three | 洛汗 | Thirty-four | Six thousand |
| Four hundred and four | 斯科特 | forty-four | ten thousand |
| Four hundred and five | 泰格 | Thirty-five | Eight thousand |

SELECT * FROM Emp ORDER BY salary;

以上查询将按照工资的升序返回结果数据。

| 纺织品出口企业代码 | 名字 | 年龄 | 薪水 |
| Four hundred and three | 洛汗 | Thirty-four | Six thousand |
| Four hundred and two | 谢恩 | Twenty-nine | Eight thousand |
| Four hundred and five | 泰格 | Thirty-five | Eight thousand |
| Four hundred and one | 安奴 | Twenty-two | Nine thousand |
| Four hundred and four | 斯科特 | forty-four | ten thousand |


通过DESC使用订单

考虑上述 Emp 表,

SELECT * FROM Emp ORDER BY salary DESC;

上述查询将按照工资的降序返回结果数据。

| 纺织品出口企业代码 | 名字 | 年龄 | 薪水 |
| Four hundred and four | 斯科特 | forty-four | ten thousand |
| Four hundred and one | 安奴 | Twenty-two | Nine thousand |
| Four hundred and five | 泰格 | Thirty-five | Eight thousand |
| Four hundred and two | 谢恩 | Twenty-nine | Eight thousand |
| Four hundred and three | 洛汗 | Thirty-four | Six thousand |

查看其他 DCL 命令及其用法:



SQL GROUP BY子句

原文:https://www.studytonight.com/dbms/groupby-clause.php

Group by 子句用于根据一列或多列对SELECT查询的结果进行分组。它还与 SQL 函数一起使用,对一个或多个表的结果进行分组。

在语句中使用 Group by 的语法。

SELECT column_name, function(column_name)
FROM table_name 
WHERE condition 
GROUP BY column_name

语句中的GROUP BY示例

考虑以下 Emp 表。

| 纺织品出口企业代码 | 名字 | 年龄 | 薪水 |
| Four hundred and one | 安奴 | Twenty-two | Nine thousand |
| Four hundred and two | 谢恩 | Twenty-nine | Eight thousand |
| Four hundred and three | 洛汗 | Thirty-four | Six thousand |
| Four hundred and four | 斯科特 | forty-four | Nine thousand |
| Four hundred and five | 泰格 | Thirty-five | Eight thousand |

在这里,我们希望找到按员工的工资分组的员工的姓名年龄,或者换句话说,我们将根据他们的工资对员工进行分组,因此,我们将获得一个数据集,其中列出了唯一的工资,以及第一名员工的姓名和年龄,以获得该工资。希望你说到点子上了!

group by用于根据任意一列将不同数据行组合在一起。

上述要求的 SQL 查询将是,

SELECT name, age 
FROM Emp GROUP BY salary

结果会是,

| 名字 | 年龄 |
| 洛汗 | Thirty-four |
| 谢恩 | Twenty-nine |
| 安奴 | Twenty-two |


带有WHERE子句的语句中的GROUP BY示例

考虑以下 Emp

| 纺织品出口企业代码 | 名字 | 年龄 | 薪水 |
| Four hundred and one | 安奴 | Twenty-two | Nine thousand |
| Four hundred and two | 谢恩 | Twenty-nine | Eight thousand |
| Four hundred and three | 洛汗 | Thirty-four | Six thousand |
| Four hundred and four | 斯科特 | forty-four | Nine thousand |
| Four hundred and five | 泰格 | Thirty-five | Eight thousand |

SQL 查询将是,

SELECT name, salary 
FROM Emp 
WHERE age > 25
GROUP BY salary

结果会是。

| 名字 | 薪水 |
| 洛汗 | Six thousand |
| 谢恩 | Eight thousand |
| 斯科特 | Nine thousand |

您必须记住Group By子句总是出现在 SQL 查询的末尾,就像ORDER BY子句一样。



SQL HAVING子句

原文:https://www.studytonight.com/dbms/having-clause.php

Having 子句与 SQL 查询一起使用,为语句提供更精确的条件。它用于在基于GROUP BY的 SQL 查询中提及条件,就像WHERE子句用于SELECT查询一样。

句法HAVING从句,

SELECT column_name, function(column_name)
FROM table_name
WHERE column_name condition
GROUP BY column_name
HAVING function(column_name) condition

使用HAVING的 SQL 语句示例

考虑以下销售表。

| 似…的 | 订单名称 | 上一余额 | 顾客 |
| Eleven | ord1 | Two thousand | 亚历克斯 |
| Twelve | 订单 2 | One thousand | 圣经》和《古兰经》传统中)亚当(人类第一人的名字 |
| Thirteen | ord3 | Two thousand | 全面 |
| Fourteen | ord4 | One thousand | 圣经》和《古兰经》传统中)亚当(人类第一人的名字 |
| Fifteen | ord5 | Two thousand | 亚历克斯 |

假设我们想找到往期 _ 余额之和大于 3000客户

我们将使用下面的 SQL 查询,

SELECT *
FROM sale GROUP BY customer
HAVING sum(previous_balance) > 3000

结果会是,

| 似…的 | 订单名称 | 上一余额 | 顾客 |
| Eleven | ord1 | Two thousand | 亚历克斯 |

上述 SQL 查询的主要目的是根据之前对客户进行的所有销售,找出拥有超过 3000previous_balance 的客户的姓名,因此我们得到客户Alex的表中第一行。



DISTINCT关键字

原文:https://www.studytonight.com/dbms/distinct-keyword.php

distinct关键字与SELECT语句一起使用,从表中检索唯一值。Distinct从数据库的任何表中检索记录时,删除所有重复记录。


DISTINCT关键字的语法

SELECT DISTINCT column-name FROM table-name;

使用DISTINCT关键字的示例

考虑以下 Emp 表。如下表所示,有员工名字,还有员工工资年龄

在下表中,多名员工的工资相同,因此我们将使用DISTINCT关键字列出不同的工资金额,即当前支付给员工的工资。

| 纺织品出口企业代码 | 名字 | 年龄 | 薪水 |
| Four hundred and one | 安奴 | Twenty-two | Five thousand |
| Four hundred and two | 谢恩 | Twenty-nine | Eight thousand |
| Four hundred and three | 洛汗 | Thirty-four | ten thousand |
| Four hundred and four | 斯科特 | forty-four | ten thousand |
| Four hundred and five | 泰格 | Thirty-five | Eight thousand |

SELECT DISTINCT salary FROM Emp;

以上查询将只返回 Emp 表中的唯一薪资。

| 薪水 |
| Five thousand |
| Eight thousand |
| ten thousand |



SQL ANDOR运算符

原文:https://www.studytonight.com/dbms/sql-and-or-operator.php

ANDOR运算符与WHERE子句一起使用,通过将多个条件组合在一起,为从数据库中获取数据创造更精确的条件。


AND运算符

AND运算符用于设置多个条件,如WHERE子句、旁边的、SELECTUPDATEDELETE SQL 查询。


AND运算符示例

考虑以下 Emp

| 纺织品出口企业代码 | 名字 | 年龄 | 薪水 |
| Four hundred and one | 安奴 | Twenty-two | Five thousand |
| Four hundred and two | 谢恩 | Twenty-nine | Eight thousand |
| Four hundred and three | 洛汗 | Thirty-four | Twelve thousand |
| Four hundred and four | 斯科特 | forty-four | ten thousand |
| Four hundred and five | 泰格 | Thirty-five | Nine thousand |

SELECT * FROM Emp WHERE salary < 10000 **AND** age > 25

以上查询将返回工资小于10000****年龄大于 25 的记录。希望你明白这里的概念。我们用AND运算符用WHERE子句指定了两个条件。

| 纺织品出口企业代码 | 名字 | 年龄 | 薪水 |
| Four hundred and two | 谢恩 | Twenty-nine | Eight thousand |
| Four hundred and five | 泰格 | Thirty-five | Nine thousand |


OR运算符

OR运算符也用于将多个条件与WHERE子句组合在一起。ANDOR唯一的区别是它们的行为。

当我们使用AND组合两个或两个以上的条件时,结果中会出现满足所有指定条件的记录。

但是对于OR运算符,结果集中的任何记录必须满足指定条件中的至少一个条件。


OR运算符示例

考虑以下 Emp

| 纺织品出口企业代码 | 名字 | 年龄 | 薪水 |
| Four hundred and one | 安奴 | Twenty-two | Five thousand |
| Four hundred and two | 谢恩 | Twenty-nine | Eight thousand |
| Four hundred and three | 洛汗 | Thirty-four | Twelve thousand |
| Four hundred and four | 斯科特 | forty-four | ten thousand |
| Four hundred and five | 泰格 | Thirty-five | Nine thousand |

SELECT * FROM Emp WHERE salary > 10000 OR age > 25 

以上查询将返回或者工资大于 10000 或者年龄大于 25 的记录。

| Four hundred and two | 谢恩 | Twenty-nine | Eight thousand |
| Four hundred and three | 洛汗 | Thirty-four | Twelve thousand |
| Four hundred and four | 斯科特 | forty-four | ten thousand |
| Four hundred and five | 泰格 | Thirty-five | Nine thousand |



SQL 中的除法运算符

原文:https://www.studytonight.com/dbms/division-operator.php

当我们必须评估包含关键字ALL的查询时,使用除法运算符。

使用除法运算符的一些情况是:

  1. 哪个人在某个城市的所有银行都有账户?
  2. 哪些学生修完了毕业所需的所有课程?

在上述指定的问题陈述中,关键字'all'后的描述定义了一个包含一些元素的集合,最终结果包含那些满足这些要求的单元。

另一种识别除法运算符用法的方法是使用if...then的逻辑蕴涵。在上面两个例子的上下文中,我们可以看到查询意味着,

  1. 如果在那个特定的城市有一家银行,那个人必须在那个银行有一个账户。
  2. 如果在要求毕业的课程列表中有一门课程,那么这个人一定上过这门课程。

不要担心,如果你不清楚所有这些新的东西,我们会试着在继续学习本教程的时候解释清楚。

我们将详细看到上面提到的第二个例子。

表 1:课程 _ 选修 →由学生姓名和所选课程组成。

| 学生名 | 课程 |
| 罗伯特 | 数据库 |
| 罗伯特 | 编程语言 |
| 大卫 | 数据库 |
| 大卫 | 操作系统 |
| 汉纳 | 编程语言 |
| 汉纳 | 机器学习 |
| 汤姆(男子名) | 操作系统 |

表 2:课程 _ 必修 →由一个人为了毕业需要修的课程组成。

| 课程 |
| 数据库 |
| 编程语言 |


使用除法运算符

现在,让我们尝试找出正确的 SQL 查询来获取第一个需求的结果,即:

查询:找到所有能毕业的同学。(即修完一个人毕业所需的所有科目。)

不幸的是,我们没有直接的方法来表达除法运算符。让我们一步步来,为除法运算符编写查询。

1.找到所有的学生

创建一组所有已学习课程的学生。这可以使用以下命令轻松完成。

CREATE TABLE AllStudents AS SELECT DISTINCT Student_Name FROM Course_Taken

该命令将返回表所有学生,作为结果集:

| 学生名称 |
| 罗伯特 |
| 大卫 |
| 汉纳 |
| 汤姆(男子名) |


2.找到所有的学生和毕业所需的课程

接下来,我们将创建一组学生和他们毕业所需的课程。我们可以用所有学生课程 _ 必修的笛卡尔乘积的形式来表达,使用以下命令。

CREATE table StudentsAndRequired AS 
SELECT AllStudents.Student_Name, Course_Required.Course
FROM AllStudents, Course_Required

现在新的结果集表学生和要求的将是:

| 学生名 | 课程 |
| 罗伯特 | 数据库 |
| 罗伯特 | 编程语言 |
| 大卫 | 数据库 |
| 大卫 | 编程语言 |
| 汉纳 | 数据库 |
| 汉纳 | 编程语言 |
| 汤姆(男子名) | 数据库 |
| 汤姆(男子名) | 编程语言 |


3.找到所有学生和他们没有上过的必修课

在这里,我们为找到不能毕业的学生迈出了第一步。这个想法就是简单地找到那些没有修过毕业所需课程的学生,这样他们就不能毕业了。这只是存在于学生和必需的中而不存在于课程中的所有元组/行。

CREATE  table StudentsAndNotTaken AS 
SELECT * FROM StudentsAndRequired WHERE NOT EXISTS 
(Select * FROM Course_Taken WHERE StudentsAndRequired.Student_Name = Course_Taken.Student_Name 
AND StudentsAndRequired.Course = Course_Taken.Course)

学生和非学生出来是:

| 学生名 | 课程 |
| 大卫 | 编程语言 |
| 汉纳 | 数据库 |
| 汤姆(男子名) | 数据库 |
| 汤姆(男子名) | 编程语言 |


4.查找所有无法毕业的学生

所有在桌子上的学生都是不能毕业的。因此,我们可以找到不能毕业的学生,

CREATE table CannotGraduate AS SELECT DISTINCT Student_Name FROM StudentsAndNotTaken

| 学生名称 |
| 大卫 |
| 汉纳 |
| 汤姆(男子名) |


5.找到所有能毕业的学生

能够毕业的学生仅仅是那些出现在全体学生但不在不能毕业的学生。这可以通过以下查询来完成:

CREATE Table CanGraduate AS SELECT * FROM AllStudents 
WHERE NOT EXISTS 
(SELECT * FROM CannotGraduate WHERE 
    CannotGraduate.Student_name = AllStudents.Student_name)

结果如下:

| 学生名称 |
| 罗伯特 |

因此,我们刚刚了解到,不同的步骤如何引导我们找到最终答案。现在让我们看看如何在一个查询中编写所有这 5 个步骤,这样我们就不必创建这么多表。

SELECT DISTINCT  x.Student_Name FROM Course_Taken AS x WHERE NOT 
EXISTS(SELECT * FROM Course_Required AS y WHERE NOT 
EXISTS(SELECT * FROM Course_Taken AS z 
    WHERE z.Student_name = x.Student_name 
    AND z.Course = y.Course ))

| 学生名称 |
| 罗伯特 |

这给了我们和上面 5 步一样的结果。



高级 SQL

SQL 约束

原文:https://www.studytonight.com/dbms/sql-constraints.php

SQL 约束是用于限制可以进入表中的数据类型的规则,以保持表中数据的准确性和完整性。

约束可以分为以下两种类型,

  1. 列级约束:仅限制列数据。
  2. 表级约束:限制整表数据。

约束用于确保数据库中数据的完整性。以下是可应用于表的最常用的约束。

  • 不为空
  • 独一无二的
  • 主关键字
  • 外键
  • 支票
  • 系统默认值

NOT NULL约束

默认情况下,可以保存空值。如果不希望列具有空值,请使用非空约束。

  • 它限制列不能有空值。
  • 我们使用 ALTER 语句和 MODIFY 语句来指定这个约束。

关于这个约束需要注意的一点是,它不能在表级别定义。

使用NOT NULL约束的示例:

CREATE TABLE Student
(  	s_id int NOT NULL, 
   	name varchar(60), 
   	age  int
);

以上查询将声明学生表的 s_id 字段不取空值。

如果您希望在创建表之后更改它,那么我们可以对它使用 alter 命令:

ALTER TABLE Student
MODIFY s_id int NOT NULL;

UNIQUE约束

它确保一列只有唯一的值。唯一约束字段不能有任何重复数据。

  • 它防止两个记录在一列中具有相同的值
  • 我们使用 ALTER 语句和 MODIFY 语句来指定这个约束。

唯一约束的示例:

这里我们有一个简单的CREATE查询来创建一个表,该表将有一个带有唯一值的列 s_id

CREATE TABLE Student
( 	s_id int  NOT NULL, 
  	name varchar(60), 
  	age int  NOT NULL UNIQUE
);

以上查询将声明学生表的 s_id 字段只有唯一的值,不会取空值。

如果您希望在创建表之后更改它,那么我们可以对它使用 alter 命令:

ALTER TABLE Student
MODIFY age INT NOT NULL UNIQUE;

以上查询指定学生表的 s_id 字段只有唯一值。


主键约束

主键约束唯一标识数据库中的每条记录。主键必须包含唯一值,并且不能包含空值。通常主键用于索引表中的数据。

表级主键约束

CREATE table Student 
(	s_id int PRIMARY KEY, 
	Name varchar(60) NOT NULL, 
	Age int);

上述命令将在s_id上创建一个主键。

列级主键约束

ALTER table Student 
ADD PRIMARY KEY (s_id);

上述命令将在s_id上创建一个主键。


外键约束

外键用于关联两个表。两个表之间的关系匹配其中一个表中的主键和第二个表中的外键。

  • 这也称为引用键。
  • 我们使用 ALTER 语句和 ADD 语句来指定这个约束。

为了理解外键,让我们借助下表来看看它的用法:

客户 _ 明细

| c_id | 客户名称 | 地址 |
| One hundred and one | 圣经》和《古兰经》传统中)亚当(人类第一人的名字 | 无聊死了 |
| One hundred and two | 亚历克斯 | 德里 |
| One hundred and three | 斯图亚特 | 罗塔克 |

订单 _ 明细

| 订单 id | 订单名称 | c_id |
| Ten | 订单 1 | One hundred and one |
| Eleven | 订单 2 | One hundred and three |
| Twelve | 订单 3 | One hundred and two |

Customer_Detail 表中, c_id 是主键,在 Order_Detail 表中设置为外键。在 Order_Detail 表中设置为外键的 c_id 中输入的值必须出现在 Customer_Detail 表中,在该表中该值被设置为主键。这样可以防止无效数据被插入到 Order_Detail 表的 c_id 列。

如果您试图插入任何不正确的数据,DBMS 将返回错误,并且不允许您插入数据。

表级外键约束

CREATE table Order_Detail(
    order_id int PRIMARY KEY, 
    order_name varchar(60) NOT NULL,
    c_id int FOREIGN KEY REFERENCES Customer_Detail(c_id)
);

在该查询中,表 Order_Detail 中的 c_id 作为外键,是对 Customer_Detail 表中 c_id 列的引用。

列级外键约束

ALTER table Order_Detail 
ADD FOREIGN KEY (c_id) REFERENCES Customer_Detail(c_id);

删除时外键列的行为

当主表中的特定记录被删除时,有两种方法可以保持子表中数据的完整性。当两个表用 Foriegn 键连接,主表中的某些数据被删除,子表中存在某条记录时,那么我们必须有某种机制来保存子表中数据的完整性。

foriegn key behaviour on delete - cascade and Null

  1. 删除级联时:如果 foriegn 键的值从主表中删除,这将从子表中删除记录。
  2. 删除空值时:这将把子表的该记录中的所有值设置为空值,为此从主表中删除外键的值。
  3. 如果我们不使用以上任何一项,那么我们就不能从主表中删除子表中存在数据的数据。如果我们试图这样做,我们会得到一个错误。
ERROR : Record in child table exist

CHECK约束

检查约束用于将列的值限制在一个范围内。在将值存储到数据库之前,它会对这些值进行检查。这就像在将数据保存到列中之前进行条件检查。


在表级使用CHECK约束

CREATE table Student(
    s_id int NOT NULL CHECK(s_id > 0),
    Name varchar(60) NOT NULL,
    Age int
);

以上查询将限制 s_id 值大于零。


在列级使用CHECK约束

ALTER table Student ADD CHECK(s_id > 0);

相关教程:



什么是 SQL 函数?

原文:https://www.studytonight.com/dbms/sql-function.php

SQL 提供了许多内置函数来对数据执行操作。这些函数在执行数学计算、字符串连接、子字符串等时非常有用。SQL 函数分为两类,

  1. 聚合函数
  2. 标量函数

聚合函数

这些函数在对一组值进行计算后返回一个值。以下是一些常用的聚合函数。


AVG()功能

Average 根据数值列中的值计算平均值后返回平均值。

它的通用语法是,

SELECT AVG(column_name) FROM table_name

使用 AVG()函数

考虑以下 Emp

| 纺织品出口企业代码 | 名字 | 年龄 | 薪水 |
| Four hundred and one | 安奴 | Twenty-two | Nine thousand |
| Four hundred and two | 谢恩 | Twenty-nine | Eight thousand |
| Four hundred and three | 洛汗 | Thirty-four | Six thousand |
| Four hundred and four | 斯科特 | forty-four | ten thousand |
| Four hundred and five | 泰格 | Thirty-five | Eight thousand |

SQL 查询查找平均工资将、

SELECT **avg(salary)** from Emp;

上述查询的结果将是,

| 平均工资 |
| Eight thousand two hundred |


COUNT()功能

Count 根据某个条件或无条件返回表中的行数。

它的通用语法是,

SELECT COUNT(column_name) FROM table-name

使用 COUNT()函数

考虑以下 Emp

| 纺织品出口企业代码 | 名字 | 年龄 | 薪水 |
| Four hundred and one | 安奴 | Twenty-two | Nine thousand |
| Four hundred and two | 谢恩 | Twenty-nine | Eight thousand |
| Four hundred and three | 洛汗 | Thirty-four | Six thousand |
| Four hundred and four | 斯科特 | forty-four | ten thousand |
| Four hundred and five | 泰格 | Thirty-five | Eight thousand |

满足指定条件对员工进行计数 SQL 查询是,

SELECT COUNT(name) FROM Emp WHERE salary = 8000;

上述查询的结果将是,

| 计数(名称) |
| Two |


计数示例(独特)

考虑以下 Emp

| 纺织品出口企业代码 | 名字 | 年龄 | 薪水 |
| Four hundred and one | 安奴 | Twenty-two | Nine thousand |
| Four hundred and two | 谢恩 | Twenty-nine | Eight thousand |
| Four hundred and three | 洛汗 | Thirty-four | Six thousand |
| Four hundred and four | 斯科特 | forty-four | ten thousand |
| Four hundred and five | 泰格 | Thirty-five | Eight thousand |

SQL 查询是,

SELECT COUNT(DISTINCT salary) FROM emp;

上述查询的结果将是,

| 计数(独特的工资) |
| four |


FIRST()功能

First 函数返回选定列的第一个值

【FIRST 函数的语法为:

SELECT FIRST(column_name) FROM table-name;

使用第一()函数

考虑以下 Emp

| 纺织品出口企业代码 | 名字 | 年龄 | 薪水 |
| Four hundred and one | 安奴 | Twenty-two | Nine thousand |
| Four hundred and two | 谢恩 | Twenty-nine | Eight thousand |
| Four hundred and three | 洛汗 | Thirty-four | Six thousand |
| Four hundred and four | 斯科特 | forty-four | ten thousand |
| Four hundred and five | 泰格 | Thirty-five | Eight thousand |

SQL 查询将是,

SELECT FIRST(salary) FROM Emp;

结果是,

| 第一名(工资) |
| Nine thousand |


LAST()功能

函数的作用是:返回所选列的最后一个值。

LAST 函数的语法为,

SELECT LAST(column_name) FROM table-name;

使用 LAST()函数

考虑以下 Emp

| 纺织品出口企业代码 | 名字 | 年龄 | 薪水 |
| Four hundred and one | 安奴 | Twenty-two | Nine thousand |
| Four hundred and two | 谢恩 | Twenty-nine | Eight thousand |
| Four hundred and three | 洛汗 | Thirty-four | Six thousand |
| Four hundred and four | 斯科特 | forty-four | ten thousand |
| Four hundred and five | 泰格 | Thirty-five | Eight thousand |

SQL 查询将是,

SELECT LAST(salary) FROM emp;

上述查询的结果将是,

| 最后(工资) |
| Eight thousand |


MAX()功能

函数的作用是:从表的选定列中返回最大值。

MAX 函数的语法为,

SELECT MAX(column_name) from table-name;

使用 MAX()函数

考虑以下 Emp

| 纺织品出口企业代码 | 名字 | 年龄 | 薪水 |
| Four hundred and one | 安奴 | Twenty-two | Nine thousand |
| Four hundred and two | 谢恩 | Twenty-nine | Eight thousand |
| Four hundred and three | 洛汗 | Thirty-four | Six thousand |
| Four hundred and four | 斯科特 | forty-four | ten thousand |
| Four hundred and five | 泰格 | Thirty-five | Eight thousand |

查询最大工资,

SELECT MAX(salary) FROM emp;

上述查询的结果将是,

| 最高工资 |
| ten thousand |


MIN()功能

函数的作用是:从表中选定的一列返回最小值。

MIN 函数的语法为:

SELECT MIN(column_name) from table-name;

使用最小()函数

考虑以下 Emp 表,

| 纺织品出口企业代码 | 名字 | 年龄 | 薪水 |
| Four hundred and one | 安奴 | Twenty-two | Nine thousand |
| Four hundred and two | 谢恩 | Twenty-nine | Eight thousand |
| Four hundred and three | 洛汗 | Thirty-four | Six thousand |
| Four hundred and four | 斯科特 | forty-four | ten thousand |
| Four hundred and five | 泰格 | Thirty-five | Eight thousand |

SQL 查询查找最低工资是,

SELECT MIN(salary) FROM emp;

结果会是,

| 最低工资 |
| Six thousand |


SUM()功能

SUM 函数返回所选列数值的总和。

SUM 的语法是,

SELECT SUM(column_name) from table-name;

使用 SUM()函数

考虑以下 Emp

| 纺织品出口企业代码 | 名字 | 年龄 | 薪水 |
| Four hundred and one | 安奴 | Twenty-two | Nine thousand |
| Four hundred and two | 谢恩 | Twenty-nine | Eight thousand |
| Four hundred and three | 洛汗 | Thirty-four | Six thousand |
| Four hundred and four | 斯科特 | forty-four | ten thousand |
| Four hundred and five | 泰格 | Thirty-five | Eight thousand |

SQL 查询查找工资总额将是,

SELECT SUM(salary) FROM emp;

上述查询的结果是,

| 工资总额 |
| Forty-one thousand |


标量函数

标量函数从输入值返回单个值。以下是 SQL 中一些常用的标量函数。


UCASE()功能

UCASE 函数用于将字符串列的值转换为大写字符。

UCASE 的语法

SELECT UCASE(column_name) from table-name;

使用 UCASE()函数

考虑以下 Emp

| 纺织品出口企业代码 | 名字 | 年龄 | 薪水 |
| Four hundred and one | 国立大学 | Twenty-two | Nine thousand |
| Four hundred and two | 谢恩 | Twenty-nine | Eight thousand |
| Four hundred and three | 洛汗 | Thirty-four | Six thousand |
| Four hundred and four | 斯科特 | forty-four | ten thousand |
| Four hundred and five | 泰格 | Thirty-five | Eight thousand |

使用 UCASE 的 SQL 查询是,

SELECT UCASE(name) FROM emp;

导致

| UCASE(名称) |
| 澳洲国立大学 |
| 谢恩 |
| 洛汗 |
| 斯科特 |
| 老虎 |


LCASE()功能

LCASE 函数用于将字符串列的值转换为小写字符。

【LCASE 的语法是,

SELECT LCASE(column_name) FROM table-name;

使用 LCASE()函数

考虑以下 Emp

| 纺织品出口企业代码 | 名字 | 年龄 | 薪水 |
| Four hundred and one | 安奴 | Twenty-two | Nine thousand |
| Four hundred and two | 谢恩 | Twenty-nine | Eight thousand |
| Four hundred and three | 洛汗 | Thirty-four | Six thousand |
| Four hundred and four | 斯科特 | forty-four | ten thousand |
| Four hundred and five | 泰格 | Thirty-five | Eight thousand |

用于将字符串值转换为小写的 SQL 查询是,

SELECT LCASE(name) FROM emp;

结果会是,

| LCASE(名称) |
| 国立大学 |
| 谢恩 |
| 洛汗 |
| 斯科特 |
| 老虎 |


MID()功能

MID 函数用于从表中字符串类型的列值中提取子字符串。

MID 功能的语法是,

SELECT MID(column_name, start, length) from table-name;

使用 MID()函数

考虑以下 Emp

| 纺织品出口企业代码 | 名字 | 年龄 | 薪水 |
| Four hundred and one | 国立大学 | Twenty-two | Nine thousand |
| Four hundred and two | 谢恩 | Twenty-nine | Eight thousand |
| Four hundred and three | 洛汗 | Thirty-four | Six thousand |
| Four hundred and four | 斯科特 | forty-four | ten thousand |
| Four hundred and five | 泰格 | Thirty-five | Eight thousand |

SQL 查询将是,

SELECT MID(name,2,2) FROM emp;

结果会是,

| MID(名称,2,2) |
| 希腊字母第 13 字 |
| 哈 |
| 哦 |
| 总裁 |
| 互联网门户 |


ROUND()功能

ROUND 函数用于将数值字段舍入到最接近的整数。它用于小数点值。

Round 函数的语法是,

SELECT ROUND(column_name, decimals) from table-name;

使用 ROUND()函数

考虑以下 Emp

| 纺织品出口企业代码 | 名字 | 年龄 | 薪水 |
| Four hundred and one | 国立大学 | Twenty-two | Nine thousand point six seven |
| Four hundred and two | 谢恩 | Twenty-nine | Eight thousand point nine eight |
| Four hundred and three | 洛汗 | Thirty-four | Six thousand point four five |
| Four hundred and four | 斯科特 | forty-four | ten thousand |
| Four hundred and five | 泰格 | Thirty-five | Eight thousand point zero one |

SQL 查询是,

SELECT ROUND(salary) from emp;

结果会是,

| ROUND(工资) |
| Nine thousand and one |
| Eight thousand and one |
| Six thousand |
| ten thousand |
| Eight thousand |



SQL JOIN

原文:https://www.studytonight.com/dbms/joining-in-sql.php

SQL Join 用于从两个或多个表中获取数据,这些表被连接起来以显示为一组数据。它用于通过使用两个或多个表共有的值来组合这两个表中的列。

JOIN关键字用于连接两个或多个表的 SQL 查询。加入表的最低要求条件是 (n-1) ,其中 n 是表的数量。一个表也可以自己连接,这就是所谓的自连接


JOIN 的类型

以下是我们可以在 SQL 中使用的连接类型:

  • 内部的
  • 外面的
  • 左边的
  • 对吧

交叉连接或笛卡尔乘积

这种类型的 Join 返回来自 JOIN 中的表的行的笛卡尔乘积。它将返回一个由记录组成的表,这些记录将第一个表中的每一行与第二个表中的每一行组合在一起。

交叉连接语法是,

SELECT column-name-list
FROM 
table-name1 CROSS JOIN table-name2;

交叉连接的例子

以下是表,

| 身份 | 名字 |
| one | 全面 |
| Two | 亚当 |
| four | 亚历克斯 |

类信息表,

| 身份 | 地址 |
| one | 德里 |
| Two | 孟买 |
| three | chennai |

Cross JOIN 查询将、

SELECT * FROM 
class CROSS JOIN class_info;

结果集表如下所示,

| 身份 | 名字 | 身份 | 地址 |
| one | 全面 | one | 德里 |
| Two | 亚当 | one | 德里 |
| four | 亚历克斯 | one | 德里 |
| one | 全面 | Two | 孟买 |
| Two | 亚当 | Two | 孟买 |
| four | 亚历克斯 | Two | 孟买 |
| one | 全面 | three | chennai |
| Two | 亚当 | three | chennai |
| four | 亚历克斯 | three | chennai |

如您所见,这个连接返回两个表中所有记录的叉积。


内部连接或等价连接

这是一个简单的连接,根据 SQL 查询中指定的相等条件,结果基于匹配的数据。

内部连接语法是,

SELECT column-name-list FROM 
table-name1 INNER JOIN table-name2 
WHERE table-name1.column-name = table-name2.column-name;

INNER JOIN 示例

考虑一个表,

| 身份 | 名字 |
| one | 全面 |
| Two | 亚当 |
| three | 亚历克斯 |
| four | 国立大学 |

类信息表,

| 身份 | 地址 |
| one | 德里 |
| Two | 孟买 |
| three | chennai |

内部 JOIN 查询将、

SELECT * from class INNER JOIN class_info where class.id = class_info.id;

结果集表如下所示,

| 身份 | 名字 | 身份 | 地址 |
| one | 全面 | one | 德里 |
| Two | 亚当 | Two | 孟买 |
| three | 亚历克斯 | three | chennai |


Natural JOIN

自然联接是一种内部联接,它基于要联接的两个表中具有相同名称和相同数据类型的列。

自然连接的语法是,

SELECT * FROM 
table-name1 NATURAL JOIN table-name2;

自然连接的例子

这里是表,

| 身份 | 名字 |
| one | 全面 |
| Two | 亚当 |
| three | 亚历克斯 |
| four | 国立大学 |

类信息表,

| 身份 | 地址 |
| one | 德里 |
| Two | 孟买 |
| three | chennai |

自然联接查询将,

SELECT * from class NATURAL JOIN class_info; 

结果集表如下所示,

| 身份 | 名字 | 地址 |
| one | 全面 | 德里 |
| Two | 亚当 | 孟买 |
| three | 亚历克斯 | chennai |

在上面的例子中,两个被连接的表都有标识列(相同的名称和相同的数据类型),因此两个表中标识的值匹配的记录将是这两个表自然连接的结果。


外部连接

外部联接基于匹配和不匹配的数据。外部连接进一步细分为,

  1. 左外连接
  2. 右外连接
  3. 完全外部连接

左外连接

左外部连接返回一个结果集表,其中有来自两个表的匹配数据,然后是表的剩余行,以及来自表的列的空值。

左外连接的语法是,

SELECT column-name-list FROM 
table-name1 LEFT OUTER JOIN table-name2
ON table-name1.column-name = table-name2.column-name;

要指定一个条件,我们使用ON关键字和外部连接。

甲骨文的左外连接语法是,

SELECT column-name-list FROM 
table-name1, table-name2 on table-name1.column-name = table-name2.column-name(**+**);

左外连接示例

这里是表,

| 身份 | 名字 |
| one | 全面 |
| Two | 亚当 |
| three | 亚历克斯 |
| four | 国立大学 |
| five | 阿施施 |

类信息表,

| 身份 | 地址 |
| one | 德里 |
| Two | 孟买 |
| three | chennai |
| seven | 无聊死了 |
| eight | 帕尼帕特 |

左外连接查询将是,

SELECT * FROM class LEFT OUTER JOIN class_info ON (class.id = class_info.id); 

结果集表如下所示,

| 身份 | 名字 | 身份 | 地址 |
| one | 全面 | one | 德里 |
| Two | 亚当 | Two | 孟买 |
| three | 亚历克斯 | three | chennai |
| four | 国立大学 | 空 | 空 |
| five | 阿施施 | 空 | 空 |


右外连接

右外连接返回一个结果集表,其中来自两个被连接的表的匹配数据,然后是表的剩余行,剩余的表的列为空。

右外连接的语法是,

SELECT column-name-list FROM 
table-name1 RIGHT OUTER JOIN table-name2 
ON table-name1.column-name = table-name2.column-name;

甲骨文的右外连接语法是,

SELECT column-name-list FROM 
table-name1, table-name2 
ON table-name1.column-name(**+**) = table-name2.column-name;

右外连接示例

再次表,

| 身份 | 名字 |
| one | 全面 |
| Two | 亚当 |
| three | 亚历克斯 |
| four | 国立大学 |
| five | 阿施施 |

类信息表,

| 身份 | 地址 |
| one | 德里 |
| Two | 孟买 |
| three | chennai |
| seven | 无聊死了 |
| eight | 帕尼帕特 |

右外连接查询将是,

SELECT * FROM class RIGHT OUTER JOIN class_info ON (class.id = class_info.id); 

生成的表看起来像,

| 身份 | 名字 | 身份 | 地址 |
| one | 全面 | one | 德里 |
| Two | 亚当 | Two | 孟买 |
| three | 亚历克斯 | three | chennai |
| 空 | 空 | seven | 无聊死了 |
| 空 | 空 | eight | 帕尼帕特 |


完全外部连接

完全外部连接返回一个结果集表,其中有两个表的匹配数据,然后是左表和右表的剩余行。****

完全外部联接的语法是,

SELECT column-name-list FROM 
table-name1 FULL OUTER JOIN table-name2
ON table-name1.column-name = table-name2.column-name;

全外连接的例子是,

表,

| 身份 | 名字 |
| one | 全面 |
| Two | 亚当 |
| three | 亚历克斯 |
| four | 国立大学 |
| five | 阿施施 |

类信息表,

| 身份 | 地址 |
| one | 德里 |
| Two | 孟买 |
| three | chennai |
| seven | 无聊死了 |
| eight | 帕尼帕特 |

全外连接查询会是这样的,

SELECT * FROM class FULL OUTER JOIN class_info ON (class.id = class_info.id);

结果集表如下所示,

| 身份 | 名字 | 身份 | 地址 |
| one | 全面 | one | 德里 |
| Two | 亚当 | Two | 孟买 |
| three | 亚历克斯 | three | chennai |
| four | 国立大学 | 空 | 空 |
| five | 阿施施 | 空 | 空 |
| 空 | 空 | seven | 无聊死了 |
| 空 | 空 | eight | 帕尼帕特 |

现在我们已经学习了 SQL JOIN,您也可以查看这些 SQL 主题及其用法:



SQL 别名——AS关键字

原文:https://www.studytonight.com/dbms/sql-alias.php

别名用于给表或列取别名,也可以是结果集表。这在大型或复杂查询的情况下非常有用。别名主要用于为具有复杂名称的列或表提供短别名。

表名别名的语法,

SELECT column-name FROM table-name AS alias-name

下面是一个使用别名的 SQL 查询,

SELECT * FROM Employee_detail AS ed;

定义列别名的语法如下:

SELECT column-name AS alias-name FROM table-name;

使用列别名的示例,

SELECT customer_id AS cid FROM Emp;

SQL 查询中的别名示例

考虑以下两个表,

表,

| 身份 | 名字 |
| one | 全面 |
| Two | 亚当 |
| three | 亚历克斯 |
| four | 国立大学 |
| five | 阿施施 |

类信息表,

| 身份 | 地址 |
| one | 德里 |
| Two | 孟买 |
| three | chennai |
| seven | 无聊死了 |
| eight | 帕尼帕特 |

下面是使用 SQL 别名从两个表中获取数据的查询,

SELECT C.id, C.Name, Ci.Address from Class AS C, Class_info AS Ci where C.id = Ci.id;

结果集表看起来像,

| 身份 | 名字 | 地址 |
| one | 全面 | 德里 |
| Two | 亚当 | 孟买 |
| three | 亚历克斯 | chennai |

SQL Alias 似乎是 SQL 的一个非常简单的特性,但是当您处理 3 个以上的表并且必须在它们上面使用 JOIN 时,它非常有用。



SQL 中的集合运算

原文:https://www.studytonight.com/dbms/set-operation-in-sql.php

SQL 支持很少可以对表数据执行的集合操作。这些用于在不同的特殊条件下从存储在表中的数据中获得有意义的结果。

在本教程中,我们将介绍 4 种不同类型的 SET 操作,以及示例:

  1. 联盟
  2. 联合所有
  3. 横断
  4. 负的

联合行动

UNION 用于组合两个或多个SELECT语句的结果。但是,它将从结果集中删除重复的行。对于 union,在应用 UNION 操作的两个表中,列数和数据类型必须相同。

union set operation in sql


UNION 示例

第一张表,

| 身份 | 名字 |
| one | 全面 |
| Two | 亚当 |

第二张表,

**| 身份 | 名字 |
| Two | 亚当 |
| three | 切斯特 |

联合 SQL 查询将是,

SELECT * FROM First 
UNION
SELECT * FROM Second;

结果集表如下所示,

| 身份 | 名字 |
| one | 全面 |
| Two | 亚当 |
| three | 切斯特 |


联合所有

这个操作类似于 Union。但是它也显示了重复的行。

union all set operation in sql

联合所有的例子

第一张表,

| 身份 | 名字 |
| one | 全面 |
| Two | 亚当 |

第二张表,

**| 身份 | 名字 |
| Two | 亚当 |
| three | 切斯特 |

联合所有查询将是这样的,

SELECT * FROM First 
UNION ALL
SELECT * FROM Second;

结果集表如下所示,

| 身份 | 名字 |
| one | 全面 |
| Two | 亚当 |
| Two | 亚当 |
| three | 切斯特 |


横断

Intersect 操作用于组合两个SELECT语句,但它只重新运行两个SELECT语句共有的记录。如果相交,列数和数据类型必须相同。

注意: MySQL 不支持 INTERSECT 运算符。

intersect set operatoin in sql

相交示例

第一张表,

| 身份 | 名字 |
| one | 全面 |
| Two | 亚当 |

第二张表,

**| 身份 | 名字 |
| Two | 亚当 |
| three | 切斯特 |

相交查询将是,

SELECT * FROM First 
INTERSECT
SELECT * FROM Second;

结果集表如下所示

| 身份 | 名字 |
| Two | 亚当 |


负的

减操作将两个SELECT语句的结果组合起来,只返回最终结果中属于结果第一集的那些。

minus set operation in sql

减的例子

第一张表,

| 身份 | 名字 |
| one | 全面 |
| Two | 亚当 |

第二张表,

**| 身份 | 名字 |
| Two | 亚当 |
| three | 切斯特 |

减去查询将是,

SELECT * FROM First 
MINUS
SELECT * FROM Second;

结果集表如下所示,

| 身份 | 名字 |
| one | 全面 |



什么是 SQL 序列?

原文:https://www.studytonight.com/dbms/sql-sequences.php

序列是一些数据库系统支持的一个特性,可以按需产生唯一的值。一些 DBMS 如 MySQL 支持AUTO_INCREMENT代替顺序。

AUTO_INCREMENT应用于列,每次向表中插入新记录时,它会自动将列值增加1

序列也有些类似于AUTO_INCREMENT但是它也有一些额外的特性。


创建序列

创建序列的语法是,

CREATE SEQUENCE sequence-name
    START WITH initial-value
    INCREMENT BY increment-value
    MAXVALUE maximum-value
    CYCLE | NOCYCLE;
  • 初始值指定序列的起始值。
  • 增量值是序列增加的值。
  • 最大值指定了序列自身递增的上限或最大值。
  • 关键字CYCLE指定如果最大值超过设定的限制,序列将从开始重新开始它的循环。
  • 并且,NO CYCLE指定如果序列超过MAXVALUE值,将抛出一个错误。

在 SQL 查询中使用序列

让我们从创建一个序列开始,从1开始,递增1,最大值为999

CREATE SEQUENCE seq_1
START WITH 1
INCREMENT BY 1
MAXVALUE 999
CYCLE;

现在让我们使用上面刚刚创建的序列。

下面我们有一个表,

| 身份 | 名字 |
| one | 全面 |
| Two | 亚当 |
| four | 亚历克斯 |

该查询将是,

INSERT INTO class VALUE(seq_1.nextval, 'anu');

结果集表看起来像,

| 身份 | 名字 |
| one | 全面 |
| Two | 亚当 |
| four | 亚历克斯 |
| one | 国立大学 |

一旦使用nextval,即使没有在表中插入任何记录,序列也会递增。



SQL 视图

原文:https://www.studytonight.com/dbms/sql-views.php

SQL 中的视图是一个或多个表中数据的逻辑子集。视图用于限制数据访问。

创建视图的语法,

CREATE or REPLACE VIEW view_name 
    AS
    SELECT column_name(s)
    FROM table_name
    WHERE condition

通过查看上面的 SQL 查询,您可能已经理解了,视图是使用从其他表中获取的数据创建的。它更像是用数据创建的临时表。


创建视图

考虑遵循销售表,

| 似…的 | 订单名称 | 上一余额 | 顾客 |
| Eleven | ord1 | Two thousand | 亚历克斯 |
| Twelve | 订单 2 | One thousand | 圣经》和《古兰经》传统中)亚当(人类第一人的名字 |
| Thirteen | ord3 | Two thousand | 全面 |
| Fourteen | ord4 | One thousand | 圣经》和《古兰经》传统中)亚当(人类第一人的名字 |
| Fifteen | ord5 | Two thousand | 亚历克斯 |

从上表创建视图的 SQL 查询将是,

CREATE or REPLACE VIEW sale_view 
AS 
SELECT * FROM Sale WHERE customer = 'Alex';

SELECT语句提取的数据将存储在另一个名为 sale_view 的对象中。我们也可以分别使用CREATEREPLACE,但是两者一起使用效果更好,就好像任何具有指定名称的视图都存在一样,这个查询会用新的数据替换它。


显示视图

在视图中显示数据的语法类似于使用SELECT语句从表中获取数据。

SELECT * FROM sale_view;

强制视图创建

FORCE关键字在创建视图时使用,非常有力。即使表不存在,该关键字也用于创建视图。创建强制视图后,如果我们创建基表并在其中输入值,视图将自动更新。

强制视图的语法是,

CREATE or REPLACE FORCE VIEW view_name AS
    SELECT column_name(s)
    FROM table_name
    WHERE condition;

更新视图

UPDATE视图命令与表格命令相同。

更新视图的语法是,

UPDATE view-name SET VALUE
WHERE condition;

注意:如果我们更新一个视图,它也会自动更新基表数据。


只读视图

我们可以创建一个带有只读选项的视图来限制对该视图的访问。

创建只读视图的语法

CREATE or REPLACE FORCE VIEW view_name AS
    SELECT column_name(s)
    FROM table_name
    WHERE condition WITH read-only; 

以上语法将为只读目的创建视图,我们不能将数据更新或插入只读视图。它会抛出一个错误


视图类型

有两种类型的视图,

  • 简单视图
  • 复杂视图

| 简单视图 | 复杂视图 |
| 从一个表创建 | 从一个或多个表创建 |
| 不包含函数 | 包含函数 |
| 不包含数据组 | 包含多组数据 |



MongoDB

介绍

NoSQL 简介

原文:https://www.studytonight.com/mongodb/what-is-nosql

你们中的许多人可能已经知道,NoSQL 基本上是一个用于管理大量非结构化数据集的数据库,其中的数据不像关系数据库那样以表格关系存储。大多数现有的关系数据库都无法解决一些复杂的现代问题,例如:

  • 数据结构、半结构、非结构和多态数据的性质不断变化。
  • 应用程序现在为不同地理位置、不同时区的数百万用户提供服务,并且必须一直运行,同时保持数据完整性
  • 随着许多应用程序转向云计算,应用程序变得越来越分散。

NoSQL 在企业应用程序中扮演着至关重要的角色,该应用程序需要访问和分析云基础架构中多个虚拟服务器(基于远程)上可用的大量数据集,并且主要是在数据集未结构化时。因此,NoSQL 数据库旨在克服关系数据库中的性能、可伸缩性、数据建模和分布限制。


什么是结构化数据?

结构化数据通常是文本文件,具有定义的列标题和行数据。这些数据可以很容易地以图表的形式可视化,并且可以使用数据挖掘工具进行处理。

什么是非结构化数据?

非结构化数据可以是任何东西,如视频文件、图像文件、PDF、电子邮件等。这些文件有什么共同点,什么都没有。结构化信息可以从非结构化数据中提取,但这一过程非常耗时。随着越来越多的现代数据是非结构化的,有必要为不断增长的应用程序存储此类数据,从而为 NoSQL 开辟道路。


NoSQL 数据库类型

以下是 NoSQL 数据库类型:

  • 文档数据库:在这种类型中,键与称为“文档”的复杂数据结构配对。示例:MongoDB
  • 图形存储:这种类型的数据库通常用于存储网络数据。我们可以在现有数据的基础上关联数据。
  • 键值存储:这些是最简单的 NoSQL 数据库。在这种情况下,每个都存储有一个密钥来识别它。在一些键值数据库中,我们甚至可以保存保存的数据类型,就像在 Redis 中一样。
  • 宽列存储:用于存储大型数据集(将多列数据存储在一起)。例如:卡珊德拉(用于脸书)、糖化血红蛋白等。

NoSQL 数据库的一些优点

在这里,我们将通过示例讨论 NoSQL 数据库的一些主要优势。

动态模式

你一定想知道动态模式是什么意思?在像甲骨文、MySQL 这样的关系数据库中,我们定义了表结构,对吗?例如,如果我们想要保存学生数据的记录,那么我们将不得不创建一个名为 Student 的表,向其中添加列,如 student_idstudent_name 等,这被称为已定义的模式,在其中我们在保存任何数据之前定义结构。

如果将来我们计划在我们的学生表中添加更多的相关数据,那么我们将不得不在我们的表中添加一个新的列。这很简单,如果我们的表中数据较少,但是如果我们有数百万条记录呢。迁移到更新的模式将是一项繁忙的工作。NoSQL 数据库解决了这个问题,因为在 NoSQL 数据库中,不需要模式定义。

碎片

在分片中,大型数据库被划分为更小、更快且易于管理的数据库。

(经典的)关系数据库遵循一种垂直架构,在这种架构中,由于所有数据都是相关的,所以在单个服务器中保存数据。默认情况下,关系数据库不提供分片功能,为了实现这一点,必须付出很多努力,因为在关系数据库的情况下,事务完整性(在事务中插入/更新数据)、多表连接等在分布式体系结构中不容易实现。

默认情况下,NoSQL 数据库具有分片功能。不需要额外的努力。它们自动将数据分散到服务器上,在最快的时间内从空闲的服务器上获取数据,同时保持数据的完整性。

分身术

默认情况下,NoSQL 数据库也支持自动数据复制。因此,如果一台数据库服务器出现故障,将使用其在网络中另一台服务器上创建的副本来恢复数据。

集成缓存

许多 NoSQL 数据库都支持集成缓存,在集成缓存中,经常需要的数据存储在缓存中,以使查询更方便。


MongoDB- NoSQL 数据库

MongoDB 是一个用 C++语言编写的 NoSQL 数据库。它的一些驱动程序使用 C 编程语言作为基础。MongoDB 是一个面向文档的数据库,它将数据存储在集合中而不是表中。MongoDB 最棒的地方在于,几乎所有流行的编程语言都可以使用驱动程序。

在当今竞争激烈的技术世界中,每个公司都开始通过云托管其企业应用程序,以便在全球范围内扩展业务,提供更快的服务,并使客户对应用程序和整体业务的体验个性化。而 NoSQL 已经成为数据库技术中开发此类应用的首选。



MongoDB 简介

原文:https://www.studytonight.com/mongodb/introduction-to-mongodb

MongoDB 是一个 NoSQL 数据库,它以键值对的形式存储数据。这是一个开源文档数据库,它提供了高性能和可扩展性,以及企业应用程序中大量数据集的数据建模和数据管理。

MongoDB 还提供了自动缩放功能。因为,MongoDB 是一个跨平台的数据库,可以安装在不同的平台上,如视窗、Linux 等。


什么是基于文档的存储?

一个文档只不过是一个带有名称-值对的数据结构,就像在 JSON 中一样。用 MongoDB 文档映射任何编程语言的任何自定义对象都非常容易。例如:Student对象有属性namerollnosubjects,其中主体为列表。

MongoDB 中的学生文档如下所示:

{
	name : "Stduytonight",
	rollno : 1,
	subjects : ["C Language", "C++", "Core Java"]
} 

我们可以看到,文档实际上是自定义对象的 JSON 表示。此外,通过在文档中以数组和文档(嵌入)的形式保存数据,可以避免过多的连接。


MongoDB 简史

MongoDB 是由艾略特·霍洛维茨德怀特·梅里曼2007 年开发的,当时他们在公司双击开发企业 web 应用程序时遇到了一些关系数据库的可扩展性问题。根据 MongoDB 的开发人员之一德怀特·梅里曼的说法,数据库的这个名字来源于单词巨大的,以支持处理大量数据的想法。

2009 年,MongoDB 被制作成一个开源项目,同时该公司提供商业支持服务。许多公司开始使用 MongoDB 的惊人功能。《纽约时报》使用 MongoDB 构建了一个基于网络的应用程序来提交照片。2013 年,公司正式命名为MongoDB Inc .


MongoDB 的主要特性

除了大多数 NoSQL 默认功能之外,MongoDB 还引入了一些更重要、更有用的功能:

  1. MongoDB provides high performance. Input/Output operations are lesser than relational databases due to support of embedded documents(data models) and Select queries are also faster as Indexes in MongoDB supports faster queries.

    MongoDB performs less IO operations than relational DBMS

  2. MongoDB 拥有丰富的查询语言,支持所有主要的 CRUD 操作。查询语言还提供了良好的文本搜索和聚合功能。

  3. MongoDB 的自动复制功能带来高可用性。它提供了自动故障切换机制,因为如果服务器出现故障,数据将通过备份(副本)拷贝进行恢复。

  4. 分片是 MongoDB 的一个主要特性。由于分片,水平可伸缩性是可能的。

  5. MongoDB 支持多个存储引擎。当我们以文档(NoSQL)或表格(关系 DBMS)的形式保存数据时,谁来保存数据?这是存储引擎。存储引擎管理数据如何保存在内存和磁盘上。


使用 MongoDB 的组织

下面是一些大型的著名组织,它们使用 MongoDB 作为大多数业务应用程序的数据库。

  • 砖坯黏土
  • 商务化人际关系网
  • 迈克菲
  • 坚定的
  • 通过易趣网购买
  • 大都会人寿
  • 精力


MongoDB 概述

原文:https://www.studytonight.com/mongodb/overview-of-mongodb

MongoDB 由一组数据库组成。每个数据库也由集合组成。MongoDB 中的数据存储在集合中。下图描述了 MongoDB 中的典型数据库结构。

Overview of MongoDB


MongoDB 中的数据库

MongoDB 中的数据库只不过是集合的容器。在接下来的课程中,我们将学习如何创建新的数据库、删除数据库以及如何使用现有的数据库。


MongoDB 中的集合

  • 集合只不过是一组 MongoDB 文档。这些文档相当于关系 DBMS 中表格中的一行数据。但是,与 RDBMS 相比,MongoDB 中的集合与任何集合模式都不相关。集合是存储相关数据的一种方式。由于没有模式,任何类型的文档都可以保存在一个集合中,尽管为了索引效率,建议使用相似性。文档的最大大小可以是 4MB。
  • 我们可以使用命名空间对集合进行逻辑分组和嵌套。例如:可以有一个名为db.studytonight.users的集合保存用户信息,那么就可以有像db.studytonight.forum.questionsdb.studytonight.forum.answers这样的其他集合分别存储论坛问答。
  • 如果我们在命名空间集合上创建索引,它将只应用于该命名空间。我们将在本教程的后面学习如何创建索引。
  • 一旦在集合中创建了第一个文档,就在物理上创建了集合。
  • 当我们可以将任何表单或数据保存在单个集合中时,您一定想知道为什么要创建具有不同命名空间的多个集合。这是因为,MongoDB 不会为完全不相关的文档索引属性。因此,建议将相关数据保存在集合中。

MongoDB 中的文档

MongoDB 中的文档只不过是键值对的集合。这些文档将具有动态模式,这意味着同一集合中的文档不需要拥有相同的字段集。

因为 MongoDB 被认为是一个无模式数据库,所以每个集合可以保存不同类型的对象。集合中的每个对象都被称为文档,它以类似 JSON(JavaScript 对象符号)的结构(除了键值对列表什么都没有)来表示。数据在 BSON 中存储和查询,它的二进制表示类似 JSON 的数据。您可以从本网页→ BSON 规格和 [BSON 型号](from https://docs.mongodb.com/manual/reference/bson-types/)了解更多关于 BSON 格式的信息


MongoDB 中的样本数据

Sample Data in MongoDB

注意:在上图中,字段_id代表给定文档的主键标识符。MongoDB 也以值数组的形式存储这些值。事实上,任何类型的数据都可以存储为值,不需要预先定义任何东西。换句话说,你不必预先定义要存储的数据类型,你可以存储任何你想要的东西。请记住,MongoDB 是无模式的。

文档不是由简单的标识来标识的,而是由对象标识符类型来标识的。默认的 id 是机器标识符、时间戳和进程 Id 的组合,以保持其唯一性,但用户可以将其更改为任何内容。


数组作为值的示例

{ _id : 112233,
  name : "Viraj",
  education : [
           {
              year : 2029,
              course : "BTECH",
              college : "IIT, Delhi"
            },
           {
              year : 2031,
              course : "MS",
              college : "Harvard College"
           }
  ]
}

一个文档中不同数据类型的示例

文档中字段的值可以是任何东西,包括其他文档、数组、文档数组、日期对象、字符串等。

var mydoc = {
    _id : ObjectId("5099803df3f4948bd2f98391"),
    name : { first: "Alan", last: "Turing" },
    birth : new Date('Jun 23, 1912'),
    death : new Date('Jun 07, 1954'),
    contribs : [ "Turing machine", "Turing test", "Turingery" ],
    view : NumberLong(1250000)
} 


MongoDB 与 SQL 数据库

原文:https://www.studytonight.com/mongodb/mongodb-vs-rdbms

众所周知,SQL 数据库已经统治了数据技术的世界,并且已经成为数据存储的主要来源超过 40 年。通常使用 SQL 数据库,主要用于访问关系数据库。

甲骨文微软 SQL Server 统治了这一领域,但随着网络开发市场的步伐加快,出现了使用开源数据库的转变,如 MySQLPostgres 等。但是 RDBMS 仍然是首选。

很快,足够多的数据开始呈指数级增长,可扩展性成为一个主要问题,这时候 NoSQL 开始扭转局面。

关于 NoSQL 数据库的一个很酷的事实是,它们从 1960 年就存在了,但是在最近,它们变得越来越流行,特别是因为它们提供的缩放功能。

MongoDB 和 SQL 数据库的主要区别在于它们处理数据的方式。在 SQL 数据库中,数据以传统的二维行列结构的形式存储,而在 MongoDB 中,遵循丰富的数据文档模型,这允许存储任何类型的数据。

让我们看看 MongoDB 和其他 SQL 数据库之间的一些主要区别:

| SQL 数据库 | NoSQL 数据库 |
| 关系数据库 | 非关系数据库 |
| 支持 SQL 查询语言 | 支持 JSON 查询语言 |
| 基于表格 | 基于集合和键值对 |
| 基于行 | 基于文档 |
| 基于列 | 基于字段 |
| 支持外键 | 不支持外键 |
| 支持触发器 | 不支持触发器 |
| 包含预定义的模式 | 包含动态架构 |
| 不适合分层数据存储 | 最适合分层数据存储 |
| 垂直可扩展-增加内存 | 水平可扩展-添加更多服务器 |
| 强调酸性(原子性、一致性、隔离性和持久性) | 强调 CAP 定理(一致性、可用性和分区容差) |

MongoDB 文档也符合现代编程语言中的对象结构,因为它们是 JSON 的一种形式。这使得开发人员可以轻松地将应用程序中使用的数据映射到数据库中的相关文档。而在 SQL 数据库中,用编程语言创建一个列映射到对象属性的表似乎有点乏味。



MongoDB 的优势

原文:https://www.studytonight.com/mongodb/advantages-of-mongodb

看到了 MongoDB 的良好特性后,现在每个开发人员都应该能够理解为什么将基于 NoSQL 的数据库用于大数据事务和实现可伸缩模型会更好。现在,是时候抛弃关系 DBMS 的模式定义,利用像 MongoDB 这样的无模式数据库了。让我们看看 MongoDB 的一些重要优势:

Advantages of MongoDB

  1. 首先,安装和设置 MongoDB 非常容易。
  2. MongoDB 最基本的特点是它是一个无模式数据库。不再有模式迁移。因为 MongoDB 是无模式的,所以您的代码定义了您的模式。
  3. 导出基于文档的数据模型的能力是 MongoDB 最有吸引力的优势之一。因为它以 BSON(二进制 JSON)、红宝石散列等形式存储数据的方式有助于以非常丰富的方式存储数据,同时能够保存数组和其他文档。
  4. MongoDB 支持的文档查询语言在支持动态查询方面起着至关重要的作用。
  5. 非常容易扩展。
  6. 由于 MongoDB 中数据的结构化(BSON 格式-键值对)方式,不需要复杂的连接。
  7. 与任何关系数据库相比,性能调优都非常容易。
  8. 不需要将应用程序对象映射到数据对象。
  9. 由于其使用内部存储器进行存储的特性,能够更快地访问数据。
  10. 既然它是一个 NOSQL 数据库,那么它显然是安全的,因为不能进行 SQL 注入。
  11. MongoDB 也可以用作文件系统,这有助于实现更简单的负载平衡。
  12. MongoDB 也支持正则表达式和字段搜索。
  13. MongoDB 也可以作为 windows 服务运行。
  14. 有大量的文档可用。
  15. MongoDB 不需要运行虚拟机。
  16. MongoDB 遵循其较新版本的常规发布周期。
  17. 对分片的支持是它的一个关键特性。分片是将数据存储在不同机器上的过程,以及 MongoDB 在数据增长时处理数据的能力。这导致水平缩放。使用分片,当数据增长增加时,可以写入和读取更多的数据。


什么时候切换到 MongoDB

原文:https://www.studytonight.com/mongodb/why-switch-to-mongodb

首先,MongoDB 不能替代任何传统的 RDMS 数据库。但是,考虑到 MongoDB 以 BSON(JSON 的二进制表示)的形式构建/存储数据,这是一种自我解释和人类可读的数据格式,以及它为要开发的应用程序提供缩放功能的方式,下面是一些重要的因素,这些因素清楚地表明开发人员应该使用 MongoDB 来开发他们的应用程序。


数据插入一致性

基本上,与在事务中进行插入的安全问题相比,MongoDB 喜欢更高的数据插入率。因此,写入一致性较低。如果需要写入大量数据,而又不用担心会丢失一些数据,那么 MongoDB 应该是首选,而且确实是最适合的。

数据损坏恢复

当数据恢复过程需要更快、更安全、更自动化时,首选 MongoDB。在 MySQL 中,如果数据库(一些表)损坏,您可以通过删除/更新数据来单独修复它们。在 MongoDB 中,您必须在数据库级别进行修复。但是有一个命令可以自动做到这一点,但是它会读取所有数据并将其重新写入一组新的文件。因此,如果您的数据库很大,可能需要一些时间,在这段时间内,您的数据库将被锁定。但是,这也比丢失完整的数据集要好。

负载平衡

当数据无限增长并且需要适当的负载平衡时,MongoDB 是最好的解决方案。因为它支持更快的副本设置选项及其内置的分片功能。

避免 JOINS

当开发人员不想规范化他们的数据并坚持不使用任何 JOINS 时,那么他们应该真正使用 MongoDB。例如:如果有 2 个集合学生和地址(其中一个学生可以有多个地址)。在典型的关系 DBMS 中,为了从地址表中获取与学生相关的地址,使用了 JOIN。但是,在 MongoDB 中,地址数据可以作为文档嵌入到学生集合中。因此,无需使用任何 JOIN,只需一个简单的查询就可以获取学生和地址的所有必要详细信息。

db.address.insert([
    {
        _id: 'addr1',
        name: 'Bangalore'
    },
    {
        _id: 'addr2',
        name: 'Delhi'
    }
]);

db.student.insert([
    {
        _id: 's1',
        name: 'Student1',
        address: ['addr1']
    },
    {
        **_id**: '*s2*',
        **name**: '*Student2*',
        **address**: ['*addr1*','*addr2*']
    },
]);

最适合更改模式

众所周知,每当任何关系 DBMS 中的一个表被更改时(比如添加一个新列),整个数据库很有可能被锁定,这反过来又会导致性能大幅下降。因为 MongoDB 是无模式的,所以添加新字段不会导致任何问题。

不是关系数据

当要存储的数据不需要是关系数据时,应该选择 MongoDB。

更多的原因...

  1. 尽管 SQL 数据库具有非常好的一致性,但它们在数据分区方面却很糟糕。像 MongoDB 这样的 NoSQL 数据库可以用在这个场景中。
  2. 将应用程序数据对象直接映射到基于文档的存储中非常容易。因为类似 JSON 的格式非常类似于任何编程语言中的对象表示。文档比关系 DBMS 的一组关系表更接近对象。
  3. 如果您计划创建一个数据库集群,该集群可能在地理上分布以提供加速的数据查询,那么 MongoDB 应该是您的选择。


基础

MongoDB 中的数据建模

原文:https://www.studytonight.com/mongodb/data-modelling-in-mongodb

正如前面课程中所解释的,MongoDB 中的数据是无模式的,这意味着在插入之前不需要为数据定义结构。因为 MongoDB 是一个基于文档的数据库,所以同一个集合中的任何文档都不必具有相同的字段集或结构。这有助于轻松地将文档与实体对象进行映射。一般来说,MongoDB 集合中的文档将总是共享相同的数据结构(推荐用于最佳性能,而不是强制性的)。

给定数据库中数据建模的关键因素或挑战是负载平衡,从而有效地确保性能。在对数据建模时,考虑数据的完整使用(CRUD 操作)以及数据将如何被继承是一项任务。

有两种方法可以在 MongoDB 中建立数据之间的关系:

  • 参考文件
  • 嵌入的文档

MongoDB:参考文档

这是实现存储在不同集合中的数据之间的关系的方法之一。在这种情况下,对一个集合中的数据的引用将用于连接集合之间的数据。

考虑 2 个集合booksauthors,如下图:

 {
  title: "Java in action",
  author: "author1",
  language: "English",
  publisher: {
             name: "My publications",
             founded:1990,
             location: "SF"
            }
}

{
  title: "Hibernate in action",
  author: "author2",
  language: "English",
  publisher: {
             name: "My publications",
             founded:1990,
             location: "SF"
            }
} 

在上面的例子中,publisher数据被重复。为了避免这种重复,我们可以将图书的引用添加到 publisher 数据中,而不是在每个图书条目中使用 publisher 的全部数据,如下所示:

 {
  name: "My Publciations",
  founded:1980,
  location: "CA",
  books: [111222333,444555666, ..]
}

{
   _id:111222333,
   title: "Java in action",
   author: "author1",
   language: "English"
}

{
  _id:444555666,
  title: "Hibernate in action",
  author: "author2",
  language: "English"
} 

这也可以反过来做,其中一个可以引用书籍数据中的发布者 id ,这是您的选择。


MongoDB:嵌入式文档

在这种情况下,一个集合将嵌入到另一个集合中。考虑 2 个集合studentaddress。让我们看看如何将地址嵌入学生收藏。下面是一个将单个地址嵌入学生数据的示例。

 {
  _id:123,
  name: "Student1"
}

{
  _studentId:123,
  street: "123 Street",
  city: "Bangalore",
  state: "KA"
}

{
  _studentId:123,
  street: "456 Street",
  city: "Punjab",
  state: "HR"
} 

嵌入多个地址也可以完成。请参见下面的示例:

 {
  _id:123,
  name: "Student1"
  addresses: [
      	{
             	street: "123 Street",
   		city: "Bangalore",
   		state: "KA"
        },

        {
   		street: "456 Street",
   		city: "Punjab",
   		state: "HR"
        }
    ]
} 

MongoDB 中的数据建模示例

让我们考虑一个在大学建立学生数据库的简单例子。假设有 3 个模型–StudentAddressCourse。在典型的关系 DBMS 数据库中,这 3 个模型将被转换成如下所示的 3 个表:

Data Modelling in RDBMS

因此,从上面的模型来看,如果必须添加学生的详细信息,那么应该在所有 3 个表中进行输入!!

让我们看看,同样的数据如何在 MongoDB 中建模。在 MongoDB 中,模式设计将只有一个集合Student,并将具有以下结构。

 {
   _id: 123,
   firstName: 'Test',
   lastName: 'Student',
   address :[{
           City: 'Bangalore',
           State: 'Karnataka',
           Country: 'India'
        }
    ],
   Course: 'MCA'
} 

在 MongoDB 中,与所有 3 个模型相关的数据将显示在一个集合下!!

MongoDB 提供了多种建模数据的方法。现在你知道怎么做了。

注意:集合中的字段名如上面例子中的firstNamelastName等也使用内存,可能是 10-20 字节左右。但是当数据集非常大时,这会增加大量内存。因此,对于大型数据集,建议使用短字段名来存储集合中的数据,如 fname 而不是 firstName



MongoDB 真的是无模式吗?

原文:https://www.studytonight.com/mongodb/is-mongodb-really-schemaless

众所周知,MongoDB 是无模式的。我们需要了解是什么使 MongoDB 成为一个无模式数据库。

每个关系 DBMS 数据库都有一个持久化数据的结构。所以,当数据库需要修改时,比如说某个特定表的需要修改(改变数据类型)或者从表中添加/删除一列,我们不得不提到,这个列将保存什么类型的数据。

但是,MongoDB 是一个基于文档的数据库,它不使用表和列的概念,而是使用文档和集合的概念。关于不同模块的所有参考数据将作为一个集合存储。更多关于 MongoDB 使用的 BSON 数据结构可以很容易地拥有不同类型的不同数据集和字段。

当我们说无模式时,我们实际上是指动态类型模式,而不是关系 DBMS(SQL)数据库中可用的静态类型模式。

JSON 是一种完全没有模式的数据结构,与允许您在需要时指定 XSD 的 XML 相反。

每当我们在 MongoDB 中存储一些东西时,我们知道我们存储的是什么,它是 JSON 格式的字符串、Int 或 custome Object,一旦我们试图将其存储在集合中,MongoDB 就会将其作为 JSON 格式的数据接受。

当你在某个地方读到数据迁移在 NoSQL 数据库中很容易时,这也不是绝对正确的。在某些情况下,基于文档的数据库(如 MongoDB)被证明更好,但在某些情况下,基于 SQL 的数据库占了上风。例如:迁移时的数据处理,在 NoSQL 的情况下,由于数据重复,需要更长的时间,而在标准化的 SQL 数据库中,数据重复很少。



在 Windows 和 Linux 上安装 MongoDB

原文:https://www.studytonight.com/mongodb/setup-mongodb

在之前的教程中,我们已经学习了介绍、概述、优势、特性以及何时使用 MongoDB。在本教程中,我们将学习如何在本地机器上设置 MongoDB。我们将介绍在 Windows 操作系统和 Linux 操作系统上安装 MongoDB 和相关工具的步骤。


在 Windows 上安装 MongoDB

在 Windows 机器上安装 MongoDB 非常容易。以下是安装 MongoDB 的步骤:

  1. Download MongoDB executable .msi file from the site MongoDB Download Centre. Select the latest version for Windows, the Windows Server 2008 R2 is the version if you are on Windows 7, 8 or 10.

    Installing MongoDB on Windows

  2. 双击下载的.msi文件开始安装。在安装过程中选择自定义选项,指定您想要安装 MongoDB 的自定义位置。默认安装在C:\mongodb目录下。

  3. Once the installation is successful, the below directory structure is created. We have installed our MongoDB in D:\java\mongodb

    Installing MongoDB on Windows

  4. 导航到 MongoDB 的 bin 目录,了解 MongoDB 中使用的组件。以下是运行它们的一些重要组件和文件:T21】客户

    | 成分 | .exe文件 |
    | 计算机网络服务器 | 旺德。exe |
    | 路由器 | mongos.exe |
    | mongo.exe |

  5. It is required to set up the MongoDB environment. MongoDB stores all its data under the folder data\db. It is best practice to create this directory under the folder where the MongoDB is installed. So let's create a folder named data and one more folder named db inside data folder as shown below.

    Installing MongoDB on Windows

  6. 还要创建一个日志文件夹来记录 MongoDB 数据事务。在日志文件夹下,创建一个日志文件FILE_NAME.log

  7. 现在,要验证安装是否成功,请打开命令提示符,导航到 MongoDB 已安装文件夹的 bin 目录。

  8. Execute the command mongod.exe --dbpath "DATA_DIRECTORY_PATH" to configure the data path and start the MongoDB server. Please replace the DATA_DIRECTORY_PATH with the path of data directory present inside MongoDB installed folder. On running this command, the below log will be displayed which says that the MongoDB configuration is successful and the server is up and running fine.

    Installing MongoDB on Windows

  9. Now, open another command prompt window and navigate to the bin directory of the MongoDB again, and start the MongoDB client in order to use the database system. Run the command mongo in Command Prompt and it will get connected to the MongoDB where the default database is test.

    Installing MongoDB on Windows

  10. 至此,我们已经成功地在 windows 环境中安装了 MongoDB,并且可以从 MongoDB 开始了。



MongoDB 中的数据类型

原文:https://www.studytonight.com/mongodb/datatypes-in-mongodb

众所周知,MongoDB 以称为 BSON 的二进制编码格式存储 JSON 数据,其中 JSON 数据模型实际上扩展了 BSON,以便为附加数据类型提供更大的灵活性,并有助于跨各种编程语言轻松编码和解码数据。默认情况下,JSON 中不支持像日期这样的数据类型。但是,BSON 提供了这一特点。

MongoDB 支持下面的数据类型列表。MongoDB 中的每个数据类型都有一个唯一的编号。

| 数据类型 | 数字 | 描述 |
| 两倍 | one | 用于存储浮点值 |
| 线 | Two | 常用数据类型,UTF-8 有效 |
| 目标 | three | 用于存储嵌入对象 |
| 排列 | four | 用于存储嵌入对象 |
| 二进制数据 | five | 用于存储二进制数据 |
| 不明确的 | six | 用于存储未定义的值 |
| 对象标识 | seven | 用于存储文档的标识 |
| 布尔代数学体系的 | nine | 用于存储布尔值 |
| 日期 | Ten | 用于以 UNIX 格式存储当前日期时间。 |
| 空 | Eleven | 用于存储空值 |
| 正则表达式 | Twelve | 用于存储正则表达式 |
| java 描述语言 | Thirteen | 用于存储没有作用域的 JavaScript 数据 |
| 标志 | Fourteen | 基本上用于存储字符串,但保留给使用特定符号的语言 |
| 带作用域的 Javascript | Fifteen | 用于存储带作用域的 JavaScript 数据 |
| 整数 | 16 & 18 | 用于存储数值 |
| 时间戳 | Ten | 用于跟踪文档何时被修改。 |
| 最小/最大键 | 255/127 | 用于比较最低和最高 BSON 元素的值 |



在 MongoDB 中创建和删除数据库

原文:https://www.studytonight.com/mongodb/database-create-and-drop-mongodb

在本教程中,我们将学习如何在 MongoDB 中创建和删除数据库。


MongoDB:创建数据库

打开命令提示符,使用cd命令导航到 MongoDB 的 /bin 文件夹,并在那里执行mongod命令。这将启动 MongoDB 服务器。我们必须让这个命令提示符窗口保持活动状态,因为它正在运行 MongoDB。要停止 MongoDB 服务器,只需输入exit并按回车键。

现在,打开另一个命令提示符,再次导航到 MongoDB 的 /bin 文件夹,执行命令mongo。这将打开客户端来运行 MongoDB 命令。

Connect to MongoDB

在我们运行mongo命令的命令提示窗口中,成功连接到 mongodb 后,只需键入以下命令:

use database_name

如果没有同名的数据库,这将创建一个名为 database_name 的新数据库。如果已经存在一个具有上述名称的数据库,那么它只连接到该数据库。

Use a Database in MongoDB

在上图中,它创建了一个名为 mynewdatabase 的新数据库,并将连接到该数据库。

要检查当前连接的数据库,在命令提示窗口中输入db,结果会得到当前数据库的名称。

Checking active Database in MongoDB

要查看 MongoDB 中所有数据库的列表,请使用命令show dbs

List all Databases in MongoDB

请注意,运行上述命令后,新创建的数据库 mynewdatabase 尚未列出。这是因为,还没有记录被插入到数据库中。只需插入一条记录,然后再次运行该命令,如下所示:

List all Databases in MongoDB

要插入数据,请运行以下命令。别担心,我们会在下节课详细学习。

db.student.insert({name : "Viraj" })

注意:在 MongoDB 中,test将是默认数据库。如果没有创建数据库,那么所有的数据都将存储在test数据库中。


MongoDB:删除数据库

首先使用show dbs命令检查如下所示的可用数据库列表。

List all Databases in MongoDB

如果新创建的数据库 mynewdatabase 必须删除。运行以下命令删除数据库。在删除数据库之前,请连接到需要删除的数据库。

db.dropDatabase()

Drop Database in MongoDB

现在再次检查数据库列表,以验证数据库是否被删除。

List all Databases in MongoDB

请注意,数据库 mynewdatabase 已被删除,因此不会列在数据库列表中。



MongoDB:创建集合

原文:https://www.studytonight.com/mongodb/collection-create-and-drop-mongodb

在 MongoDB 中,当集合在任何命令中被引用时,都会自动创建集合。例如,如果运行插入命令:

db.student.insert({
	name: "Viraj"
})

上面的命令将创建一个名为学生的集合,如果它在数据库中还不存在的话。但是我们可以使用createCollection()命令显式创建一个集合。createCollection 方法的语法是:

db.createCollection(name, options)

在上面的命令中,名称将是集合的名称,选项是一个文档,可用于指定集合的配置。

选项参数是可选的,您只需为集合提供一个名称就可以创建一个集合。但是如果您想配置您的集合,您可以使用各种可用的选项来这样做。以下是在 MongoDB 中创建集合的可用配置选项:

| 田 | 类型 | 描述 |
| 脱帽致意 | 布尔 | (可选)要创建有上限的集合,在中,我们指定最大大小或文档计数,以防止其超出设置的最大值。 |
| 大小 | 数字 | (可选)指定上限集合的最大字节数。如果一个集合有上限并达到其最大大小限制,MongoDB 就会从其中删除旧文档,为新文档腾出空间。 |
| 最大 | 数字 | (可选)这可用于指定上限集合中允许的最大文档数。 |
| 验证器 | 文件 | (可选)根据提供的验证规则验证插入或更新的任何文档。 |
| 验证级别 | 线 | (Optional) This is used to define how strictly validation rules must be applied to existing documents during an update.可用的值有:off没有插入或更新的验证。strict这是该选项的默认值。这指示 MongoDB 对所有插入和更新应用验证规则。moderate当我们希望仅对现有的有效文档而不是现有的无效文档应用验证规则进行插入和更新时,会用到该选项。 |
| 验证操作 | 线 | (可选)这可用于设置验证时要采取的操作,即如果任何文档未通过设置的验证,则是显示error还是仅显示warn违规。默认值为error。 |


MongoDB:创建有上限的集合

我们可以使用以下命令创建一个有上限的集合。

db.createCollection("student", { capped : true, size : 5242880, max : 5000 } )

这将创建一个名为 student 的集合,最大大小为 5 兆字节,最多 5000 个文档。


MongoDB:删除集合

可以使用以下命令轻松删除 MongoDB 数据库中的任何集合:

db.collection_name.drop()

drop()如果收集成功,方法将返回 true,否则返回 false。



MongoDB 中的 CRUD 操作

原文:https://www.studytonight.com/mongodb/crud-operations-mongodb

CRUD 操作指的是基本的插入、读取、更新和删除操作。在前一章中,我们学习了如何在 MongoDB 中创建和删除数据库。现在,让我们学习如何在 MongoDB 中执行 CRUD(创建/读取/更新/删除)操作。


MongoDB:将文档插入集合(创建)

命令db.collection.insert()将对文档集合执行插入操作。

让我们将文档插入student集合。您必须连接到数据库才能执行任何插入操作。具体如下:

db.student.insert({
	regNo: "3014",
	name: "Test Student",
	course: {
		courseName: "MCA",
		duration: "3 Years"
	},
	address: {
		city: "Bangalore",
		state: "KA",
		country: "India"
	}
})

Inserting data into MongoDB Collection

请注意,已经在名为 student 的集合中输入了一个条目。


MongoDB:从集合中查询文档(读取)

要检索(选择)插入的文档,请运行以下命令。find()命令将检索给定集合的所有文档。

db.collection_name.find()

Selecting document from MongoDB Collection

注意:请注意,检索到的记录包含一个名为_id的属性,该属性带有一个名为 ObjectId 的唯一标识符值,该值用作文档标识符。

如果要根据某些标准检索记录,应调用find()方法传递参数,然后根据指定的属性检索记录。

db.collection_name.find({"fieldname":"value"})

例如:让我们从学生集合中检索记录,其中属性 regNo3014 ,其查询如下:

db.students.find({"regNo":"3014"})

MongoDB:更新集合中的文档(更新)

为了更新 MongoDB 中集合的特定字段值,请运行以下查询。

db.**collection_name**.*update*()

update()上面指定的方法将字段名称和新值作为参数来更新文档。

让我们用 regNo 3014 更新文档集合学生的属性名称

db.student.update({
	"regNo": "3014"	
},
$set:
{
	"name":"Viraj"
})

Updating document from MongoDB Collection

您将在命令提示符下看到以下内容:

Updating document from MongoDB Collection


MongoDB:从集合中删除条目(删除)

现在让我们看看从集合中删除条目。要从集合中删除条目,请运行如下所示的命令:

db.collection_name.remove({"fieldname":"value"})

例如:db.student.remove({"regNo":"3014"})

Removing document from MongoDB Collection

请注意,运行remove()方法后,该条目已从学生集合中删除。



MongoDB 中的数据关系

原文:https://www.studytonight.com/mongodb/relationships-in-mongodb

MongoDB 中的关系用于指定一个或多个文档如何相互关联。在 MongoDB 中,可以通过嵌入方式或使用引用方式对关系进行建模。这些关系可以是以下形式:

  • 一对一
  • 一对多
  • 多对多

MongoDB:嵌入式关系

在这种方法中,一个文档将嵌入到另一个文档中(像子集一样)。


MongoDB:引用关系

在这种方法中,文档是分开保存的(学生和地址)。但是,学生文档将引用地址文档 id 字段。这基本上用于设计规范化的关系。任何 NoSQL 数据库背后的基本思想都是消除文档之间的复杂关系,MongoDB 也是这样做的。但是,在某些情况下,这些关系需要在数据库中建模。


MongoDB:一对一的关系

考虑一个学院的学生数据库,其中学院限制该学生一次只能使用一门课程。因此,这只是一对一的关系,即一名学生一次只能注册一门课程。让我们看看这是如何建模的。

One to One Relationship in MongoDB documents

上图显示有学生数据,与课程数据有关系。在 MongoDB 中,这两个集合可以嵌入到一个集合中,如下所示:

One to One Relationship in MongoDB documents


MongoDB:一对多关系

继续同一个学生数据库示例,考虑一个学生可以有多个地址(永久和当前)。让我们看看如何模拟这样一个一对多的用例。

One to Many Relationship in MongoDB documents

上面您可以看到要建模的数据,下面我们为 MongoDB 存储建模了它。

One to Many Relationship in MongoDB documents

使用这种嵌入式方法,学生的两个地址都可以通过一个查询来检索!

使用参考方法,上面的数据库可以建模如下:

One to Many Relationship in MongoDB documents

这里我们使用了地址的 ObejctIds 来引用学生文档中的地址。


MongoDB:多对多关系

考虑同一个学生数据库的例子,其中一个学生可以有不同的角色,如领袖,板球队长,足球队长等。即许多角色可以由学生完成,或者学生可以与多个角色相关联。让我们看看如何模拟这种多对多的关系。

嵌入式方法:

One to Many Relationship in MongoDB documents

参考方法:

One to Many Relationship in MongoDB documents

注意:在上面的例子中,每个角色将存储在一个单独的role文档中,并且通过它们的 ObjectIds 引用相同的内容。


高级

MongoDB 中的索引

原文:https://www.studytonight.com/mongodb/indexing-in-mongodb

SQL 编程中的索引只不过是一种特殊的数据结构,用于在数据库的给定表中轻松快速地定位记录,而不需要遍历表中的每一条记录。使用给定表的一列或多列很容易生成索引。需要注意的是,索引使用的数据结构是二叉树 (B-Tree)。

在 MongoDB 中,索引在高效执行查询方面起着至关重要的作用。基本上,如果在 MongoDB 中没有定义索引,那么它必须扫描给定集合的每个文档。因此,MongoDB 使用索引来减少给定集合中要扫描的文档数量。事实上,MongoDB 的索引或多或少类似于其他关系数据库中使用的索引。

事实上,MongoDB 在集合级别定义索引,并支持对 MongoDB 集合中的任何字段进行索引。


MongoDB 中的默认索引

Mongodb 提供了一个名为_id的默认索引,它作为访问集合中任何文档的主键。这个_id索引基本上避免了为_id字段插入两个具有相同值的文档。


使用createIndex()创建索引

要在 MongoDB 中创建索引,请运行以下命令:

db.collection_name.createIndex({field : value })

要在字段regNo上为学生集合创建索引,请运行命令db.student.createIndex({regNo : 1})

以下是运行上述命令时的输出:

{
	"createdCollectionAutomatically": false,
	"numIndexesBefore" : 1,
	"numIndexesAfter" : 2,
	"ok" : 1
}

Creating Index in MongoDB

我们还可以通过运行一个命令在多个字段上创建索引。命令将是:db.student.createIndex({regNo : 1, address : -1})

Creating Index in MongoDB


MongoDB 中的索引类型

| 变址类型 | 描述 |
| 单字段索引 | 用于在单个字段上创建索引,除了默认的_id字段外,它也可以是用户定义的。 |
| 复合指数 | MongoDB 支持多个字段的用户定义索引。 |
| 多键索引 | MongoDB 基本上使用多键索引来存储数组。MongoDB 为数组中的每个元素创建一个单独的索引。如果索引包含来自数组的元素,MongoDB 会智能地识别创建多键索引。 |
| 地理空间索引 | 用于支持地理空间坐标数据所需的查询。 |
| 文本索引 | 该索引用于在集合中搜索字符串内容 |
| 散列索引 | 用于基于哈希的分片 |

因此,有了上面提到的所有特性,索引管理是 MongoDB 应用程序的关键和核心部分。



MongoDB 中恶排序

原文:https://www.studytonight.com/mongodb/sorting-in-mongodb

对任何数据库中的数据进行排序是任何 DBMS 中至关重要的操作之一。MongoDB 提供sort()功能,以便对集合中的数据进行排序。MongoDB 中的 Sort 函数接受一个值列表和一个整数值 1 或-1,表示集合是按升序(1)还是降序(1)排序。

排序函数的语法:

db.**collection_name**.*find*().*sort*({**KEY** : 1}) 

考虑一个名为学生的集合,包含 3 条记录。现在让我们看看如何使用 MongoDB 中的sort()函数对数据进行排序。

要列出集合中的所有数据,请使用find()命令。要创建与示例中相同的示例数据,请创建一个名为student的集合,并插入 3 个带有一个字段名称和一些值的文档。在下一步中,我们将对这个样本数据运行 sort 命令。

List down collection data in MongoDB

现在运行下面的查询,以升序按名称字段对数据进行排序:

db.**student**.*find*().*sort*({**name** : 1})

List down collection data in MongoDB

现在运行下面的查询,按照名称字段的降序对数据进行排序:

db.**student**.*find*().*sort*({**name** : -1})

List down collection data in MongoDB

注意:如果未指定排序首选项(即 1 或-1),则默认情况下,集合中的文档按升序排序。



MongoDB 中的聚合

原文:https://www.studytonight.com/mongodb/aggregation-in-mongodb

MongoDB 中的聚合只不过是一个用于处理返回计算结果的数据的操作。聚合基本上将来自多个文档的数据分组,并以多种方式对这些分组的数据进行操作,以便返回一个组合结果。在 sql 中count(*)和与分组由相当于 MongoDB 聚合。

聚合函数将集合中的记录分组,并可用于提供所选组的总数(总和)、平均值、最小值、最大值等。

为了在 MongoDB 中执行聚合函数,aggregate ()是要使用的函数。以下是聚合的语法:

db.collection_name.aggregate(aggregate_operation)

现在让我们看看如何利用 MongoDB 中的聚合函数。考虑一个名为书籍的集合,数据如下所示:

注:创建一个名为书籍的收藏,有字段名-标题、价格和类型。使用db.books.find()列出集合的内容。

Aggregation in MongoDB

现在,从上面的集合中,让我们使用聚合功能将电子书在线类型的书籍分组。将使用以下命令:

db.books.aggregate([{$group : {_id: "$type", category: {$sum : 1}}}])

Group Aggregation in MongoDB

上面的聚合函数会给出结果,表示有 2 条电子书类型的记录和 2 条在线类型的记录。所以上面的聚合命令,已经根据他们的类型对我们的收集数据进行了分组。


聚合函数使用的不同表达式

| 表示 | 描述 |
| 总计 | 汇总集合中所有文档的定义值 |
| 平均美元 | 计算集合中所有文档的平均值 |
| $min | 返回集合中所有文档的最小值 |
| $max | 返回集合中所有文档值的最大值 |
| $addToSet | 将值插入数组,但在结果文档中不重复 |
| $推送 | 将值插入到结果文档的数组中 |
| $第一 | 返回源文档中的第一个文档 |
| $last | 返回源文档中的最后一个文档 |



MongoDB 中的数据备份和恢复

原文:https://www.studytonight.com/mongodb/data-backup-and-restore-mongodb

对于任何 DBMS 来说,数据备份都是至关重要且要求极高的过程之一。主要原因是很难预测数据会如何以及何时丢失。因此,无论何时设置数据库,我们都需要确保在发生任何丢失事件时为数据备份做好准备,这是一种理想且最佳的做法。

备份只不过是数据库中数据的副本,有助于在数据发生灾难性事件时重用数据库。


MongoDB:进行数据备份

为了在 mongodb 中执行数据备份过程,应该使用 mongodump 命令。这个命令将把所有存储的数据转储到 mongodb 的转储目录中。它还有助于从远程服务器备份数据。

为了正确执行数据备份,请遵循以下说明:

  1. 使用命令mongod启动 mongodb 服务器

  2. 在新的命令提示符下使用命令mongo启动 mongodb 客户端。

  3. Switch to the required collection and run the command mongodump. Since the mongodump is not actually command from mongodb shell, you need to execute the command as shown below.

    Mongodump in mongodb

  4. 从上面的截图观察者得知,集合mynewdatabase的所有数据都已经被转储。

Mongodump 基本上是从数据库中读取数据,并创建一个 BSON 文件来转储数据。Mongodump 只从数据库中写入文档。数据的最终备份将具有空间效率。数据的备份将存储在 mongodb 的 bin\dump 文件夹下。

Mongodump in mongodb

此外,使用 mongodump 还有一个缺点,当集合中的数据大于可用的系统内存时,这会对性能产生一些影响。


MongoDB:从备份中恢复数据

现在让我们学习如何在 mongodb 中恢复备份数据。数据备份基本上用于在发生丢失事件时重建数据。MongoDB 通过它的一个名为mongorestore的实用工具来帮助恢复备份数据,这也是一个命令。

下面的截图显示了如何使用 MongoDB 中的命令mongorestore恢复备份数据。

DB restore in mongodb

上面的截图显示已成功恢复转储的收集数据。



MongoDB 中的分片

原文:https://www.studytonight.com/mongodb/sharding-in-mongodb

分片是在多台机器上存储数据的机制。MongoDB 的这一特性的基本原理是支持任何应用程序都期望的数据增长。因为,在某个时间点,任何应用程序的可访问性肯定会导致数据增长,并且很难适应这样的数据增长。

考虑到在单个系统中很难管理的数据增长,拥有一个包含数据副本集的集群是一种理想的方式。因此,需要对数据进行水平缩放,而分片是在 MongoDB 中完成的。简单的分片只是增加了更多的机器来处理应用程序中突然或快速增长的数据。

MongoDB 对分片的需求:

  1. 垂直缩放比例太大
  2. 在数据备份过程中,所有数据将被写入主节点。
  3. 本地磁盘中的空间可能不足以处理数据增长。

下图显示了分片在 mongodb 环境中如何工作的概念图。

Sharding in MongoDB

让我们看看上图中所示组件的相关细节。

应用

利用 mongodb 的应用程序,需要将数据聚集在多台服务器上。

陶瓷或玻璃碎片

碎片用于存储实际数据。在任何生产环境中,每个碎片都是一个独立的副本集。

配置

配置只不过是存储集群元数据的已配置 mongodb 服务器。基本上,这些配置服务器包含集群数据集到碎片的映射。查询路由器将根据任何目标操作的元数据选择特定的分片。在任何生产环境中,实际上将有 3 台配置服务器。

请参考以下网址,从 mongodb 文档官方网站了解配置共享集群的详细步骤:

https://docs.mongodb.com/v3.0/tutorial/deploy-shard-cluster/



Java 与 MongoDB 的集成

原文:https://www.studytonight.com/mongodb/java-integration

在本文中,我们将学习如何将 MongoDB 与 Java 集成,并将探索基本的 CRUD(创建、检索、更新和删除)操作。

下载 Jar,使用mongo-Java-driver-3 . 10 . 0 . Jar。将 jar 添加到 Java 构建路径中。现在,我们已经准备好通过 Java 用 MongoDB 执行 CRUD 操作了。

在这里,我们使用了 MongoDB Compass——一个 MongoDB 的图形用户界面工具来可视化我们的查询输出。

我们可以使用这个用户界面连接到数据库,然后在这里测试我们的查询。

Java Integration in MongoDB


与 MongoDB 建立连接的 Java 代码

首先,我们必须在我们的 java 项目中添加mongo-Java-driver-3 . 10 . 0 . jar文件作为依赖项。所以我们将添加马文依赖如下:

<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>3.10.0</version>
</dependency>

要找到上述 Mongo Java 驱动的最新版本,请查看以下链接。

下面我们有一个简单的带有main()方法的 Java 类,它使用MongoClient类来建立与 MongoDB 的连接。

package com.mongo;

import com.mongodb.DB; 
import com.mongodb.MongoClient; 

public class MakeConnection { 
	public static void main(String[] args) {
		try { 
			// code to create the connection
			MongoClient mongoClient = new MongoClient("localhost", 27017); 
			// code to connect to the database
			DB db = mongoClient.getDB("DemoDB");

			System.out.println("Database DemoDB connected successfully");
		} 
		catch(Exception e) { 
			e.printStackTrace(); 
		} 
	}
}

当执行上述代码时,控制台上将产生以下输出:

Java Integration in MongoDB

注意:如果你使用的是旧版的 mongodb java 驱动,也就是< = 2.10.0,那么你应该使用下面的代码和Mongo类来创建连接。

// code to create the connection
Mongo mongo = new Mongo("localhost", 27017); 
// code to connect to the database
DB db = mongoClient.getDB("DemoDB"); 

如果您的 MongoDB 以身份验证模式运行,那么您必须在连接到数据库时提供用户名和密码,如下所示:

// code to connect to the database with authentication
DB db = mongoClient.getDB("DemoDB");
boolean auth = db.authenticate("username", "password".toCharArray()); 

MongoDB:显示所有数据库

一旦我们能够使用MongoClient成功建立连接,我们就可以使用以下代码来显示所有可用的数据库:

// display all the databases
mongoClient.getDatabaseNames().forEach(System.out::println); 

上述代码的输出将是:

本地 0.000GB 解调 0.000GB

上面用于显示所有数据库列表的 java 代码类似于 MySQL 命令show databases;


MongoDB:创建集合

如果我们想从我们的 java 程序中创建一个集合(就像关系数据库中的表一样),我们可以这样做:

package com.mongo;

import com.mongodb.DB; 
import com.mongodb.MongoClient;
import com.mongodb.BasicDBObject; 

public class MakeConnection { 
	public static void main(String[] args) {
		try { 
			// code to create the connection
			MongoClient mongoClient = new MongoClient("localhost", 27017); 
			// code to connect to the database
			DB db = mongoClient.getDB("DemoDB");

			db.createCollection("User", new BasicDBObject());
			System.out.println("Collection User created successfully");

		} 
		catch(Exception e) { 
			e.printStackTrace(); 
		} 
	}
}

执行上述代码后,将在我们的数据库中创建一个名为 User 的新集合。

您也可以在 MongoDB 指南针用户界面中看到这些集合。

Java Integration in MongoDB



MongoDB 和 Java:插入文档

原文:https://www.studytonight.com/mongodb/data-insertion-mongodb

我们将继续收集用户的数据,这些数据是我们在连接到 MongoDB 数据库后创建的。让我们考虑在我们的集合用户中插入数据的各种场景。


将文档插入集合,默认_id

假设我们想在用户集合中创建一个文档,其中包含字段名称描述,我们将使用以下代码片段:

package com.mongo;

import com.mongodb.DB; 
import com.mongodb.MongoClient; 
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;

public class MakeConnection { 
	public static void main(String[] args) {
		try { 
			// code to create the connection
			MongoClient mongoClient = new MongoClient("localhost", 27017); 
			// code to connect to the database
			DB db = mongoClient.getDB("DemoDB");

			// get the User collection from DB
			DBCollection userCollection = db.getCollection("User");
			BasicDBObject bO = new BasicDBObject();

			bO.put("name", "XYZ");
			bO.put("description", "Data insertion in MongoDB");

			// inserting data into collection
			userCollection.insert(bO);
		} 
		catch(Exception e) { 
			e.printStackTrace(); 
		} 
	}
}

在上面的代码片段中,我们使用getCollection()方法获取现有集合用户。然后创建一个BasicDBObject对象,并将字段名称描述放入有值的对象中。生成的输出可以使用 MongoDB Compass 工具看到。

Data Insertion in MongoDB

作为执行上述代码的结果,使用随机生成的_id值创建了一个具有名称和描述的新条目。


通过自定义将文档插入集合_id

在任何集合中创建文档(插入数据)时,mongoDB 都提供自己的唯一 id ,称为 _id 。如果我们想提供自己的自定义 id,我们可以提供。请参考下面的代码片段。

package com.mongo;

import com.mongodb.DB; 
import com.mongodb.MongoClient; 
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;

public class MakeConnection { 
	public static void main(String[] args) {
		try { 
			// code to create the connection
			MongoClient mongoClient = new MongoClient("localhost", 27017); 
			// code to connect to the database
			DB db = mongoClient.getDB("DemoDB");

			// get the User collection from DB
			DBCollection userCollection = db.getCollection("User");
			BasicDBObject bO = new BasicDBObject();

			// adding custom _id
			bO.put("_id", "xyz123");
			bO.put("name", "XYZ");
			bO.put("description", "Data insertion in MongoDB");

			// inserting data into collection
			userCollection.insert(bO);
		} 
		catch(Exception e) { 
			e.printStackTrace(); 
		} 
	}
}

当执行上述程序时,一个新的文档被插入到集合中,其值与为_id字段提供的值一起提供。

Data Insertion in MongoDB

在输出中,我们可以发现该文档是用我们唯一的自定义 id 创建的:xyz123



MongoDB 和 Java:更新文档

原文:https://www.studytonight.com/mongodb/data-updation-mongodb

在更新数据库的任何集合中的文档数据时,我们会遇到各种场景,让我们一步一步地分析它们。


更新单个字段值

我们将更新字段name并将其值更改为 ABC 。为此,我们必须首先找到正确的文档来更新值,这可以使用一些已知的字段来完成。在我们的案例中,我们将找到具有_idxyz123 的文档,该文档将在我们的查询中充当条件,然后我们将更新name字段的值。

package com.mongo;

import com.mongodb.DB; 
import com.mongodb.MongoClient; 
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;

public class MakeConnection { 
	public static void main(String[] args) {
		try { 
			// code to create the connection
			MongoClient mongoClient = new MongoClient("localhost", 27017); 
			// code to connect to the database
			DB db = mongoClient.getDB("DemoDB");

			// get the User collection from DB
			DBCollection userCollection = db.getCollection("User");

			// condition query to get document which has to be updated
			BasicDBObject queryObj = new BasicDBObject();
			queryObj.put("_id", "xyz123");

			// create new document with data to be updated
			BasicDBObject newObj = new BasicDBObject();
			newObj.put("name", "ABC");

			// updating data into collection
			userCollection.update(queryObj, newObj);
		} 
		catch(Exception e) { 
			e.printStackTrace(); 
		} 
	}
}

在上述情况下,现有文档将被完全替换,这意味着如果它有除name字段之外的一些其他字段,那么这些字段将被删除。但我们不想那样,对吧。我们希望能够只更新任何文档中的单个值,在这种情况下,我们应该使用更新修改器$set

$set更新修饰符是一个关键字,它通知 mongo 在文档中只应该更新提供的字段

让我们更新上面的代码:

package com.mongo;

import com.mongodb.DB; 
import com.mongodb.MongoClient; 
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;

public class MakeConnection { 
	public static void main(String[] args) {
		try { 
			// code to create the connection
			MongoClient mongoClient = new MongoClient("localhost", 27017); 
			// code to connect to the database
			DB db = mongoClient.getDB("DemoDB");

			// get the User collection from DB
			DBCollection userCollection = db.getCollection("User");

			// condition query to get document which has to be updated
			BasicDBObject queryObj = new BasicDBObject();
			queryObj.put("_id", "xyz123");

			// create new document with data to be updated
			BasicDBObject newObj = new BasicDBObject();
			newObj.put("$set", new BasicDBObject.append("name", "ABC"));

			// updating data into collection
			userCollection.update(queryObj, newObj);
		} 
		catch(Exception e) { 
			e.printStackTrace(); 
		} 
	}
}

上面的代码给出了更新任何文档的正确方法。上述程序的输出将是:

Data Updation in MongoDB

字段名称的值从 xyz 更新为 ABC

在上述情况下,现有文档为


更新文档字段中的数组

考虑一个场景,我们有一个字段朋友的数组

Data Updation in MongoDB

如果我们想通过添加值来更新这个数组,我们可以参考下面的代码片段:

Data Updation in MongoDB

而阿米特则是加入了对场阵友方

Data Updation in MongoDB


更新文档字段中的对象

我们甚至可以使用更新查询将对象添加到对象数组中。举个例子,针对场评论,如果我们想添加多个各种场的对象,是可以的。

下面是代码片段:

Data Updation in MongoDB

相应的输出是:

Data Updation in MongoDB



MongoDB 和 Java:检索和删除文档

原文:https://www.studytonight.com/mongodb/retrieve-delete-mongodb

在本教程中,我们将学习如何从存储在集合中的任何文档中检索或获取数据,以及如何删除存储在任何集合中的任何现有文档。

这些功能相当于 MySQL 中的SELECTDELETE查询


检索文档

如果我们想用_id xyz123 从文档中检索字段friends的数据,可以借助下面的代码片段来完成:

Retrieve Data in MongoDB

控制台上产生的输出是:

Retrieve Data in MongoDB


删除文档

现在,在我们的好友字段中,我们有数据为【安迪】****【约翰】【阿米特】。如果我们想从列表中删除“约翰”,我们可以借助下面的代码。

Delete Data in MongoDB

查询的输出是:

Delete Data in MongoDB

“约翰”被移出赛场好友



PL/SQL

基础

PL/SQL 概述

原文:https://www.studytonight.com/plsql/overview-of-plsql

PL/SQL 代表结构化查询语言的过程语言扩展。基本上,SQL 用于执行创建数据库、在数据库中存储数据、更新数据库中的数据、检索数据库中存储的数据等基本操作,而 PL/SQL 是一种完全结构化的过程化语言,它使开发人员能够将 SQL 的功能与其过程化语句结合起来。


PL/SQL 的特点

以下是 PL/SQL 的一些有用特性:

  1. Portable:

    PL/SQL 应用程序可以在我们安装了 oracle 的所有类型的操作系统上执行。

  2. Efficient:

    无需使用 oracle 引擎,PL/SQL 就可以高效地执行各种计算。这提高了事务性能。

  3. Error-checking:

    PL/SQL 允许错误检查,并在发生错误时显示用户友好的消息。

  4. Development tool:

    PL/SQL 支持 SQL 语句的执行以及变量声明、条件语句、循环和分支、过程、函数和触发器的功能。

  5. Exception Handling:

    PL/SQL 代码能够处理可能影响程序流程的异常,因此有助于使代码更加可靠。

有了 PL/SQL 中的上述特性,可以在使用数据库的实际项目中看到 PL/SQL 编程的效用。因为它能够在数据库上执行各种逻辑操作,而这些操作不能使用简单的 SQL 查询来执行。

例如,考虑到我们有一个学校管理系统数据库,我们想查看最近 5 年在学校录取的学生名单以及他们缴纳的费用。与此同时,我们想加上给教师和非教师的工资总额。我们不能仅仅通过执行 SQL 查询来获取这些记录,我们可能能够收集数据,但是这需要多个 SQL 查询。

另一方面,如果我们使用 PL/SQL,我们可以在 PL/SQL 程序中编写过程或方法来执行数据库上的复杂逻辑。另一个优点是,我们还可以轻松检测错误,因为它显示用户友好的消息,甚至支持异常处理。


PL/SQL 架构

PL/SQL 体系结构由以下三个组件组成,如下图所示:

Image of PLSQL ARCHITECTURE FLOW

让我们了解这三个组成部分是什么,

  1. PL/SQL Block:

    PL/SQL 块创建描述要执行的进程的结构化逻辑代码块。这样的块由 SQL 语句和 PL/SQL 指令组成,然后传递给 oracle 引擎执行。我们将在下一个教程中详细了解这一点。

  2. PL/SQL Engine:

    包含过程语句的 PL/SQL 块由 PL/SQL 引擎内部的 PL/SQL 语句执行器执行。简单地说,PL/SQL 引擎提供了执行 PL/SQL 块的环境。

  3. Database Server:

    最后但同样重要的是,数据库服务器。这可以是甲骨文数据库服务器或 MySQL 数据库服务器。数据库服务器将数据存储在表中。

下面我们有一个 3 个组件的简单图示:

Image of PLSQL 3 components



PL/SQL 块

原文:https://www.studytonight.com/plsql/plsql-block

在 PL/SQL 程序中,代码是分块编写的。每个 PL/SQL 块有 3 个部分,分别是:

  1. 声明部分
  2. 开始部分
  3. 例外部分

随后是结尾的 END 语句。


PL/SQL 块

PL/SQL 块创建描述要执行的进程的结构化逻辑代码块。这样的块由 SQL 语句和 PL/SQL 指令组成,然后传递给 oracle 引擎执行。PL/SQL 块由以下四个部分组成:

  • DECLARE Section:

    PL/SQL 代码从一个声明部分开始,在该部分中可以声明内存变量和其他 oracle 对象,如游标、触发器等,如果需要也可以初始化。一旦声明/初始化,我们就可以在 SQL 语句中使用它们来进行数据操作。因为我们不需要在每个 PL/SQL 代码中要求变量等,所以这个部分是可选的。

  • BEGIN Section:

    本节包含需要执行的 SQL 和 PL/SQL 语句,并包含主要逻辑。这个部分负责处理数据检索和操作,可能是处理分支,可以使用循环和条件语句等。

  • EXCEPTION Section:

    此部分是可选的。主要用于处理 BEGINEXCEPTION 区间可能出现的错误。

  • END Section:

    这部分是 PL/SQL 块结束的指示。


是时候举个例子了!

让我们从编写一个基本的 PL/SQL 块开始,它什么都不会做,或者只是在控制台中打印一些东西。这将帮助我们理解语法。

BEGIN
   NULL;
END;

上面的 PL/SQL 块没有 DECLARE 部分,只有 BEGINEND 部分。它不会做任何事情,因为NULL语句不会做任何事情。

我们能


使用 PL/SQL 块显示输出

如果您想要显示您的 PL/SQL 块的执行输出,您可以通过使用DBMS_OUTPUT.PUT_LINE语句来实现。

让我们举一个简单的例子:

BEGIN
   DBMS_OUTPUT.PUT_LINE('Hello World!');
END;
/

你好世界!

如果你仔细看上面的 PL/SQL 块,我们已经在END;语句后面多放了一个/,使用它将自动执行脚本。


匿名 PL/SQL 块

一般来说,PL/SQL 块是大程序的一部分,或者是子程序,或者是函数,或者是过程,或者是触发器等,但是它们可以独立定义,也可以执行。

当我们定义一个没有头的 PL/SQL 块时,它被称为匿名块

让我们举一个 PL/SQL 块的例子,它将添加两个数字,并在输出中显示结果:

DECLARE 
    -- declare variable a and b  
    -- and these variables have integer datatype  
   a number;  
   b number;   
BEGIN 
   a:= 7;  
   b:= 77;  
   dbms_output.put_line('Sum of the number is: ' || a + b);  
END;  
/

Eighty-four

如果你不明白我们是怎么做到的,别担心。本教程只是一个介绍,在接下来的几个教程中我们会学习到 PL/SQL 运算符、数据类型、变量等,所以点击 Next → 进入下一个教程。



PL/SQL 中的数据类型

原文:https://www.studytonight.com/plsql/datatype-in-plsql

PL/SQL 数据类型不仅仅局限于编写 SQL 查询,它们还被用在 PL/SQL 块中,就像任何其他编程语言一样。

提供数据类型指定当执行任何 PL/SQL 代码块时,Oracle 将如何存储和处理任何数据。

数据类型定义了所使用的数据类型,无论是数字、单词(字符串)还是单个字符等。根据所需的数据类型,可以在 PL/SQL 中使用以下数据类型:

PL/SQL Datatypes

因此,我们有 4 大类数据类型,它们是:

  1. 标量类型:这些是基本的数据类型,通常包含单个值,如数字或字符串。标量类型有 4 个不同的类别,在上图中列出,即数字类型字符和字符串布尔类型日期和时间等。
  2. LOB 类型:该数据类型处理大型对象,用于指定这些大型对象的位置,如文本文件、图像等,这些对象通常不存储在数据库之外。
  3. 引用类型:该数据类型用于保存指针值,指针值通常存储其他程序项的地址。
  4. 复合类型:最后但同样重要的是,顾名思义,这种类型的数据是可以单独操作/处理的单个数据的组合。

我们不会在下面介绍所有这些不同的数据类型,但我们会介绍最广泛使用的数据类型。


数量

范围: p= 1 至 38 s= -84 至 127

该数据类型用于存储数字数据。这里,p是精度s是刻度。

示例:

  1. Age NUMBER(2);其中,年龄是可以存储 2 位数的变量
  2. percentage NUMBER(4,2);其中,percent是一个可以存储小数点前 4 (p)位和小数点后 2 (s)位的变量。

CHAR(大小)

范围: 1 到 2000 字节

  • 该数据类型用于存储固定长度的字母字符串。
  • 它的值用单引号括起来。
  • 占用整个声明的内存大小,即使空间没有被数据利用。

示例:

  1. rank CHAR(10);其中, rank 是一个最多可以存储 10 个字符的变量。如果存储在 rank 中的数据长度(charcaters)是 5,那么它将仍然占据所有 10 个空间。5 内存中的空间将被使用,剩余的空白内存空间将被浪费。

VARCHAR(大小)

范围: 1 到 2000 字节

  • 该数据类型用于存储可变长度的字母数字字符串。
  • 它的值用单引号括起来。
  • 占用整个声明的内存大小,即使空间没有被数据利用。

示例:

  1. address VARCHAR(10);其中,地址是一个变量,最多可以占用 10 个字节的内存空间,并且可以在其中存储字母数字值。未使用的空间被浪费了。

VARCHAR2(尺寸)

范围: 1 到 4000 字节

  • 该数据类型用于存储可变长度的字母数字字符串。
  • 它的值用单引号括起来。
  • 它释放内存中未使用的空间,从而节省未使用的空间。

示例:

  1. name VARCHAR2(10);其中,名称是一个变量,可以占用最多 10 个字节的内存来存储一个字母数字值。释放未使用的内存空间。

日期

范围:公元前 4712 年 1 月 1 日至 9999 年 12 月 31 日

  • 它以日期格式存储数据
  • 该数据类型的值用单引号括起来。

示例:

  1. DOB DATE;其中, DOB 是以定义的格式存储出生日期的变量(即‘13-FEB-1991’)

%TYPE

  • 它存储数据类型未知的变量的值,并且当我们希望变量继承表列的数据类型时。
  • 此外,它的值通常是从数据库中的现有表中检索的,因此它采用它所用于的列的数据类型。

示例:

  1. Student sno %TYPE;,其中学生是在数据库中创建的表的名称, sno 是数据类型未知的变量,%TYPE用于存储其值。

BOOLEAN

  • 该数据类型用于条件语句。
  • 它存储逻辑值。
  • 可以是TRUE也可以是FALSE

示例:

  1. isAdmin BOOLEAN;其中, isAdmin 是一个变量,其值可以是真或假,具体取决于被检查的条件。

结论

上面介绍的数据类型是最常用的。但是还有许多不同的数据类型,您可以通过以下链接查看官方 Oracle 参考资料:

在本教程中,我们介绍了 PL/SQL 中使用的数据类型,在此过程中,我们也讨论了很多变量。如果您感到困惑,请继续下一个教程,我们已经介绍了所有关于 PL/SQL 变量的内容。



变量、常量和字面值

原文:https://www.studytonight.com/plsql/plsql-variables

在我们之前的教程中,我们介绍了 PL/SQL 数据类型 ,在本教程中,我们将学习 PL/SQL 变量、常量和文本。我们还将编写一些简单的 PL/SQL 块,看看我们如何定义变量并使用它们。

什么是标识符?

在继续之前,让我们了解什么是标识符。你被你的名字所识别,因此你的名字就是你的标识符。同样,在编程中,我们使用标识符来命名数据,数据可以是任何形式的数据。


PL/SQL 变量

变量是用于存储特定数据类型数据的保留内存区域。这是一个标识符,用于标识存储数据的存储位置。在任何 PL/SQL 块的DECLARE部分完成变量声明时,该内存被保留。

变量声明语法:

Variable_name  datatype(size);

让我们举一个简单的例子来说明如何在 PL/SQL 中定义一个变量,

roll_no NUMBER(2);

a int;

如果我们想在声明时给变量赋值,语法应该是,

Variable_name datatype(size) NOT NULL:=value;

让我们也举一个简单的例子,

eid NUMBER(2) NOT NULL := 5;

在上面的 PL/SQL 代码中,我们定义了一个名为eid的变量,该变量的数据类型为NUMBER,可以容纳多个长度为 2 的字节,这意味着它可以容纳一个高达 99 的数字(因为从 100 开始我们有 3 个数字),该变量的默认值为 5

关键字不为空表示eid不能为空。

这里,:=是一个赋值运算符,用于给变量赋值。(我们将在下一个教程中了解各种运算符)


在 PL/SQL 中声明变量的规则

以下是在定义和使用 PL/SQL 中的变量时需要记住的一些重要规则:

  1. 变量名是用户定义的。它应该以一个字符开头,后面最多可以有 29 个字符。

  2. PL/SQL 的关键字(即保留字)不能作为变量名。

  3. Multiple variables can be declared in a single line provided they must be separated from each other by at least one space and comma.

    例如:a,b,c int;

  4. Variable names containing two words should not contain space between them. It must be covered by underscore instead.

    例如:Roll_no

  5. 变量名区分大小写,表示a_varA_var不一样


是时候举个例子了!

让我们举一个简单的例子来看看如何声明一个变量并使用它,

set serveroutput on;
DECLARE
	a NUMBER(2);
	b NUMBER(2) := 5;
BEGIN
	a := b;
	dbms_output.put_line(a);
END; 

five

在上面的例子中,我们已经声明了两个变量ab,并为变量b赋值,然后在 BEGIN 块中,我们将变量b的值赋给变量a,然后在控制台上打印它的值。


PL/SQL 常量

常量是那些在声明时在整个 PL/SQL 块中保持固定的值。对于声明常数,使用constant关键字。

声明常量的语法:

Constant_Name  constant  Datatype(size) := value;

让我们举一个简单的代码例子,

school_name constant VARCHAR2(20) := "DPS";

在上面的代码示例中,常量名称是用户定义的,后跟一个关键字constant,然后我们已经声明了它的值,一旦声明就不能更改。


是时候举个例子了!

下面我们有一个简单的程序来演示常量在 PL/SQL 中的使用,

set serveroutput on;
DECLARE
	school_name constant varchar2(20) := "DPS";
BEGIN
	dbms_output.put_line('I study in '|| school_name);
END; 

我在 DPS PL/SQL 程序的学习顺利完成。


PL/SQL 通用

字面值是一个由自身表达的值,通常是常量。例如,如果你的名字是亚历克斯,那么对你来说亚历克斯是一个字面值(常量的值)。换句话说,在程序中声明为常数的值称为字面值值。字面值可以是数字、字符串或日期。

| 字面值的类型 | 说明 | 例子 |
| 数字的 | 它可以是正数,也可以是负数。 | 2,-5,10,-50 |
| 线 | 它是字符的集合,使用时用单引号括起来。 | 《你好,世界》 |
| 日期 | 它是 DD-MON-YYYY 格式的日期,在任何程序中使用时总是用单引号括起来。T3】 | ' 1995 年 11 月 25 日' |


是时候举个例子了!

这里我们有一个简单的程序来演示字面值在 PL/SQL 中的使用,

set serveroutput on;
DECLARE
	str varchar2(20):= 'Welcome to Studytonight.com';
BEGIN
	dbms_output.put_line(str);
END; 

欢迎来到 Studytonight.com

在下一个教程中,我们将学习 PL/SQL 中的运算符。



PL/SQL 中的运算符

原文:https://www.studytonight.com/plsql/plsql-operators

运算符是一种符号,它告诉编译器对与符号一起指定的一个或多个操作数执行运算。必须对其执行操作的变量称为操作数,要执行的操作由运算符符号表示。

在 PL/SQL 中,运算符可以大致分为以下几类:

  • 算术运算符
  • 关系运算符
  • 比较运算符
  • 逻辑运算符

算术运算符

算术运算符用于对操作数执行不同的数学运算。以下是 PL/SQL 中可用的算术运算符:

:为了给每个操作者提供例子,我们考虑两个变量,ab分别取值 6 和 3。

| 操作员 | 使用 | 例子 |
| + | 将两个操作数相加 | a+b将给出 9 |
| - | 执行减法,从第一个操作数中减去第二个操作数。这个运算符也可以返回负值。 | a-b将给出 3 |
| / | 执行除法运算。 | a/b将给出 2 |
| * | 执行乘法 | a*b将给出 18 |
| ** | 执行求幂运算,即第一个操作数的幂等于第二个操作数的幂 | a**b将给出 216 |


关系运算符

关系运算符用于比较两个值,并以布尔值的形式返回结果(要么是要么是)。它们主要用于需要某种比较的情况。以下是 PL/SQL 中可用的关系运算符:

:为了给每个操作者提供示例,我们考虑两个变量,ab,分别取值 7 和 14。

| 操作员 | 使用 | 例子 |
| = | 检查给定的两个操作数的值是否相等。如果它相等,那么条件将返回真或假。 | (a = b)为假 |
| !=``<>``~= | 这些运算符用于检查两个操作数是否不相等,或者它们的值是否不同。如果操作数不相等,则条件将返回 true 或 false。 | a != b是真的吗 |
| < | 检查 LHS 值是否小于 RHS 值。如果是,条件返回真。 | a < b是真的吗 |
| > | 检查 LHS 值是否大于 RHS 值。如果是,条件返回真。 | a > b为假(不为真) |
| <= | 检查 LHS 值是否小于或等于 RHS 值。 | a <= b是真的吗 |
| >= | 检查 LHS 值是否大于或等于 RHS 值 | a >= b为假(不为真) |


逻辑运算符

逻辑运算符用于组合多个表达式或定义具有两个操作数的表达式,并根据逻辑运算符周围的操作数或表达式返回TrueFalse

:为了给每个操作符提供例子,我们考虑两个变量(或表达式)ab,分别取值为真和假。

| 操作员 | 使用 | 例子 |
| AND | 当 LHS 和 RHS 操作数都为真时,返回。当 LHS 和 RHS 操作数都为假或其中之一为假时,
返回。 | a AND b将返回假 |
| OR | 当 LHS 和 RHS 操作数都为真或其中之一为真时,返回。当 LHS 和 RHS 操作数为假时,
返回。 | a OR b将返回真 |
| NOT | 应用于单个操作数。当操作数为假时,返回。当操作数为真时,
返回。 | NOT a将返回假 |

在上表中,当我们说操作数时,它也可以是表达式。在编写 SQL 查询时,我们倾向于将这些运算符与 WHERE 子句一起使用。


比较运算符

比较运算符用于将一个值与另一个值进行比较,并将结果返回为。以下是不同类型的比较运算符:

1.LIKE操作员

该运算符用于匹配单个字符或一组字符(字符串)。有两个通配符用于匹配。

%用于匹配任意字符的字符串。

_用于匹配单个字符。

这里可以看到:SQL 中 LIKE 运算符示例

如果字符串或字符匹配,该运算符返回,否则返回

SELECT * from student WHERE sname LIKE 'J%';

当我们执行上面的 SQL 查询时,它将显示名称以 J 开头的学生记录,其中%用于匹配第一个字符 J 之后的任何字符的字符串。如果学生表中有乔恩、吉亚、约翰、詹姆斯等名字,我们将得到他们。

我们再举一个例子,

SELECT * from student WHERE sname LIKE '_ _ _ a';

当我们执行上面的 SQL 查询时,它将显示学生记录,该记录的名称由 4 个字母组成,以字符 a 结尾。

2.BETWEEN操作员

该运算符用于检查值是否在某个给定范围内。如果值在给定范围内,则返回,否则返回

让我们举个例子:

SELECT * from student WHERE age BETWEEN 12 AND 18;

上面的 SQL 查询将显示年龄在 12 到 18 岁之间的学生记录。

3.IN操作员

当需要将任何值与给定的值列表进行比较时,使用该运算符。如果给定列表中存在该值,则返回,否则返回。当我们必须进行多个比较而不是使用多个OR条件时,这个运算符就派上了用场。

让我们举个例子:

SELECT * from student WHERE city IN ('Delhi','Goa','Kerela');

上面的 SQL 查询,将显示属于城市德里或果阿或凯拉的学生记录。

4.IS NULL操作员

如果操作数值为空,该运算符返回,否则返回

让我们举个例子:

SELECT * from student WHERE age IS NULL;

上面的 SQL 查询,将显示表中年龄字段为空的学生记录



进阶

条件语句

原文:https://www.studytonight.com/plsql/decision-making-plsql

决策语句是那些负责根据某种条件从多个给定语句中执行一个语句的语句。该条件将返回真或假。根据条件返回的内容,执行相关联的语句。

比如有人说,考 40 分就能通过考试,否则就不及格。在这种情况下,条件是得到 40 分,如果是真的,那么这个人将通过,否则他/她将失败。

这可以使用决策语句在 PL/SQL 块中逻辑实现。

PL/SQL 中的决策语句有两种类型:

  1. If Else 语句
  2. 选择语句

让我们用例子一个一个来看。


PL/SQL: if语句

当只有一个条件需要测试时,可以使用if语句或if...then语句。如果条件的结果是,则执行特定的动作,否则如果是,则不采取任何动作,程序的控制将移出if代码块。

语法:

if <test_condition> then
	body of action
end if; 

下面我们有一个图表,或者我们可以说一个显示使用if条件语句的流程图:

Image of Flowchart of IF statement PL/SQL

现在我们知道了if语句的目的及其语法,下面我们来看一个例子。

是时候举个例子了!

我们有一个简单的程序可以在两个给定的数字中找到最大的数字。

set serveroutput on;
DECLARE
	x int:=10;
	y int:=80;
BEGIN
	if(y>x) then
		dbms_output.put_line('Result: ' ||y|| ' is greater than ' ||x);
	end if;
END;

结果:80 大于 10 PL/SQL 过程成功完成。


PL/SQL: if...then...else声明

使用这个语句组,我们可以根据条件指定两个语句或两组语句,这样当条件为真时,执行一组语句,如果条件为假,则执行另一组语句。

语法:

if <test_condition> then
	statement 1/set of statements 1
else
	statement 2/set of statements 2
end if;

下面我们有一个图表,或者我们可以说一个显示if使用的流程图...then...else病情声明:

Image of Flowchart of IF Else statement PL/SQL

既然我们知道了if的目的是什么...then...else语句及其语法,我们来看一个例子。

是时候举个例子了!

下面我们有一个程序来查找用户给定的数字是偶数还是奇数

set serveroutput on;

DECLARE
	x int;
BEGIN
	x := &x;
	if mod(x,2) = 0 then
		dbms_output.put_line('Even Number');
	else
		dbms_output.put_line('Odd Number');
	end if;
END;

为成功完成的偶数 PL/SQL 过程输入 x:6 的值。

在上述程序中,使用了mod函数,该函数将把x的值除以 2 后的余数返回。


PL/SQL: if...then...elsif...else声明

它用于检查多个条件。在这种情况下有时需要测试多个条件if...then...else语句不能使用。为此,if...then...elsif...else语句适用于逐一测试所有条件的情况,无论哪个条件被发现为,都将执行该代码块。如果所有条件均为,则执行else部分。

在下面的语法中,可以看到首先检查条件 1 ,如果是真的,则执行后面的语句,然后控制移出完整的if块,但是如果条件是假的,则控制检查条件 2 并重复相同的过程。如果所有条件都失败,则执行else部分。

语法:

if <test_condition1> then
	body of action
elsif <test_condition2>then
	body of action
elsif<test_condition3>then
	body of action
...
...
...
else
	body of action
end if;

正如您在上面的语法中所看到的,我们可以有多个elsif语句,并且可以有任意多的条件。下面我们有一个图表,或者我们可以说一个流程图:

Image of Flowchart of IF then elsif then else statement PL/SQL

让我们看一个代码示例来更好地理解这个概念,

是时候举个例子了!

下面我们有一个程序来找出两个给定的数字是否相等,如果它们不相等,那么哪个更大。

set serveroutput on;

DECLARE
	a int;
	b int;
BEGIN
	a := &a;
	b := &b;
	if(a>b) then
		dbms_output.put_line(‘a is greater than b’);
	elsif(b>a) then
		dbms_output.put_line(‘b is greater than a’);
	else
		dbms_output.put_line(‘Both a and b are equal’);
	end if;
END;

输入值 a: 8 输入值 b: 5 a 大于 b PL/SQL 过程成功完成。


PL/SQL:案例语句

如果我们试图用一行来描述案例陈述,那么我们可以说意思是“众多中的一个”。这是一个决策声明,从多个可用选项中仅选择一个选项。

为此,它使用了一个选择器。这个选择器可以是一个变量、函数或过程,它返回一些值,并根据结果执行一个 case 语句。如果所有案例都失败,则执行else案例。

语法:

CASE selector
	when value1 then Statement1;
	when value2 then Statement2;
	...
	...
	else statement;
end CASE;

让我们举个例子来看看案例陈述是如何起作用的。

是时候举个例子了!

下面我们有一个程序来演示一个简单的案例陈述的使用。

set serveroutput on;
DECLARE
	a int;
	b int;
BEGIN
	a := &a;
	b := mod(a,2);
	CASE b
		when 0 then dbms_output.put_line('Even Number');
		when 1 then dbms_output.put_line('Odd Number');
 		else dbms_output.put_line('User has not given any input value to check');
	END CASE;
END;

输入成功完成的:7 奇数 PL/SQL 过程的值。

在上述程序中,使用了mod函数,该函数将返回a的值除以 2 后的余数。根据所选案例将被执行的情况,余数将为 0 或 1。


搜索的案例陈述

在这种类型的案例陈述中,不使用选择器,而是使用子句本身检查测试条件。当条件为时,执行其后的语句,否则依次使用子句检查其他测试条件。如果所有测试条件都失败,则执行else情况。

语法:

CASE
	when <test_condition1> then statement1;
	when <test_condition2> then statement2;
    ...
    ...
	else defaultstatement;
end case;

让我们举一个例子来看看搜索到的案例语句的作用。

是时候举个例子了!

下面我们有一个程序来演示搜索案例语句的使用。

set serveroutput on;

DECLARE
	dt Date;
	str varchar2(10);
BEGIN
	dt := '&date';
	str := to_char(dt,'DY');
	CASE
		when str in ('SAT','SUN') then dbms_output.put_line('Its the Weekend');
 		else dbms_output.put_line('Not a Weekend');
	END CASE;
END;

输入 dt:28-APR-2019 周末日期 PL/SQL 程序成功完成的值。



PL/SQL 循环

原文:https://www.studytonight.com/plsql/plsql-loops

PL/SQL 中的循环提供了一种方法,可以根据需要多次重复任何程序或任何代码语句的特定部分。

在 PL/SQL 中,当我们想要在代码块中重复执行一条语句时,我们有三个不同的循环选项可供选择。它们是:

  1. 基本循环
  2. 当循环
  3. 用于循环

在本教程中,我们将了解所有这三种循环,同时涵盖 nexted loops 的概念,这意味着循环中的循环。让我们开始吧。


基本循环

当不确定代码块要重复多少次时,在 PL/SQL 代码中首选基本循环或简单循环。当我们使用基本循环时,代码块将至少执行一次。

使用时,必须考虑以下两点:

  • 简单循环总是以关键字LOOP开始,以关键字END LOOP结束。
  • 通过使用exit语句或通过使用语句exit when指定特定条件,可以在任何给定点终止基本/简单循环。

语法:

LOOP
	sequence of statements
END LOOP; 

让我们看看下面代码示例中的简单循环。

是时候举个例子了!

在下面的代码中,我们使用循环在控制台上打印从 1 到 10 的计数,并使用exit语句来打破循环。

set serveroutput on;

DECLARE
	i int;
BEGIN
	i := 1;
	LOOP
		if i>10 then
			exit;
		end if;
		dbms_output.put_line(i);
		i := i+1;
	END LOOP;
END;

1 2 3 4 5 6 7 8 9 10 PL/SQL 程序已成功完成

让我们再举一个例子,我们将使用exit when语句来打破循环。

set serveroutput on;

DECLARE
	i int;
BEGIN
	i := 0;
	LOOP
		i := i+2
		dbms_output.put_line(i);
		exit WHEN x > 10
	END LOOP;
END;

2 4 6 8 10 PL/SQL 程序成功完成


当循环时

这是一个入口控制循环,这意味着在进入 while 循环之前,首先测试条件,如果条件为,则执行该语句或一组语句,如果条件为,则控制将移出 while 循环。

语法:

WHILE <test_condition> LOOP
	<action>
END LOOP;

让我们在下面的代码示例中看看 while 循环是如何工作的。

是时候举个例子了!

下面我们有一个简单的程序,使用 while 循环打印 1 到 10 之间的奇数。

set serveroutput on;

DECLARE
	num int:=1;
BEGIN
	while(num <= 10) LOOP
		dbms_output.put_line(''|| no);
		num := num+2;
	END LOOP;
END;

1 3 5 7 9 PL/SQL 程序成功完成。

注意:您必须编写代码来增加您放入条件中的变量值,否则变量值将保持不变,条件将始终为真。


用于循环

当 PL/SQL 代码块中的某些语句要重复固定次数时,使用此循环。

当我们使用 for 循环时,我们应该定义一个计数器变量,它根据循环开始时提供的开始和结束值来决定循环将执行多少次。

for 循环在每个循环周期结束时自动将计数器变量的值递增 1。

程序员不需要编写任何递增或递减值的指令。

语法:

FOR counter_variable IN start_value..end_value LOOP
	statement to be executed
END LOOP; 

让我们看看下面例子中的 for 循环。

是时候举个例子了!

在下面的例子中,我们使用了 for 循环来打印从 1 到 10 的数字。

set serveroutput on;
DECLARE
	i number(2);
BEGIN
	FOR i IN 1..10 LOOP
		dbms_output.put_line(i);
	END LOOP;
END;

1 2 3 4 5 6 7 8 9 10 PL/SQL 程序成功完成。

现在。让我们举另一个例子,我们将以相反的顺序打印数字。

set serveroutput on;
DECLARE
	i number(2);
BEGIN
	FOR i IN REVERSE 1..10 LOOP
		dbms_output.put_line(i);
	END LOOP;
END; 

10 9 8 7 6 5 4 3 2 1 PL/SQL 程序成功完成。

在上面的程序中, REVERSE 关键字用于以相反的顺序打印数字。



PL/SQL 字符串

原文:https://www.studytonight.com/plsql/plsql-strings

在本教程中,我们将学习 PL/SQL 中的字符串,包括各种类型的字符串,声明字符串变量的语法,然后在 PL/SQL 代码块中使用它。

就像在任何其他编程语言中一样,PL/SQL 中的字符串是字符的组合,可以是数字、特殊字符、字母或全部。

PL/SQL 为我们提供了创建可变长度字符串的自由,可以选择提供字符串的大小。

在 PL/SQL 中,基本上有三种不同类型的字符串,它们是:

  1. 固定长度的字符串:当我们定义一个固定长度的字符串时,我们必须在声明它的同时指定字符串的大小。一旦我们声明了一个固定长度的字符串,变量占用的内存空间就等于用空格填充内存空间的字符串长度。
  2. 可变长度字符串:如果是可变长度字符串,该字符串的长度最多可达 32,767 个字符。当一个可变长度字符串最初被声明时,没有为它提供空格。
  3. CLOB(字符大对象):这是一种可变长度的字符串,其大小可达 128 太字节。

PL/SQL:字符串声明的语法

当用引号括起来时,基本字面值也是字符串,例如:

'This is a string literal'

要在字符串中包含单引号,必须使用两个单引号。例如,‘你认为这是你的选择’。

为了声明一个字符串变量,我们必须指定数据类型和定义字符串最大长度的长度值。

我们可以使用像 CHAR、VARCHAR2、CLOB 等数据类型,其中每一个都用来定义不同类型的字符串。

首先我们来看看如何声明一个变长字符串变量。我们使用 VARCHAR2 数据类型。

name VARCHAR2(10)

这里,name是变量的名称,VARCHAR2 是数据类型,10 是字符串可以采用的最大长度。

现在,让我们看看如何才能声明一个固定长度的字符串变量。我们对此使用 CHAR 数据类型。声明这种类型的字符串时,可以提供也可以不提供字符串的大小/长度,因为如果不提供,Oracle 数据库会自动使用所需的最大长度。例如,

approved CHAR(1) := 'Y'
approved CHAR := 1

让我们以 PL/SQL 代码为例,我们将使用多个字符串来更好地理解这个概念。


字符串用法示例

在下面的代码示例中,我们将使用所有 3 种类型的字符串。

DECLARE 
   	s_name VARCHAR2(20); 
   	s_age NUMBER(2); 
   	s_address CLOB; 
   	s_gender CHAR(1); 
BEGIN 
   	s_name := 'Sherlock Holmes'; 
   	s_age := 21; 
   	s_address := '221B, Baker Street, London'; 
   	s_gender := 'M';
   	IF s_gender = 'M' THEN 
      	dbms_output.put_line(s_name || ' is a student at Studytonight'); 
      	dbms_output.put_line('He is ' || s_age || ' years old.'); 
      	dbms_output.put_line('He lives at ' || s_address); 
    ELSE
    	dbms_output.put_line(s_name || ' is a student at Studytonight'); 
      	dbms_output.put_line('She is ' || s_age || ' years old.'); 
      	dbms_output.put_line('She lives at ' || s_address);
   END IF; 
END; 
/

夏洛克·福尔摩斯是今晚学习的学生,他今年 21 岁。他住在伦敦贝克街 221B 号


有用的字符串函数

您可以在甲骨文网站的官方文档中找到所有字符串函数的列表和用法示例:字符串函数



PL/SQL 数组——VARRAY

原文:https://www.studytonight.com/plsql/plsql-array

在 PL/SQL 中,我们有一个名为varray的数据结构,它是一个可变大小的数组,可以用来顺序存储固定大小的相同类型的数据元素,其中元素的数量可以从零(空)到声明的最大大小不等。

varray 将数据存储在相邻的存储位置,其中第一个元素存储在最低地址位置,最后一个元素存储在最高地址位置。

要访问存储在 varray 类型变量中的数据元素,我们使用语法variable_name(index),其中index从第一个元素的 1 开始,一直到元素的当前上限,这意味着在给定点存在的元素数量(不是数组的最大大小)。

上限随着您在数组中添加或移除元素而不断变化,但它不能超过数组的最大大小。

无论何时从数据库中存储和取回 varray,其索引和元素顺序都保持稳定。

例如,在下图中,我们有一个大小为 85 的 varray Marks数据元素存储在其中。

PL/SQL varray collection

在上面的 varray Marks中如果你想访问第二个元素,你所需要做的就是Marks(2)

数据库将 varray 变量存储为单个对象。如果 varray 变量小于 4 KB,它将驻留在作为列的表中;否则,它驻留在表之外,但在同一个表空间中。


声明变量类型

我们可以使用 PL/SQL 块中的TYPE语句来声明一个新的 varray 类型。

TYPE varr_type_name IS VARRAY(n) of <element_type>

例如,

TYPE snamearray IS VARRAY(10) OF VARCHAR2(20); 
Type sagearray IS VARRAY(10) OF INTEGER;

在上面的例子中,我们初始化了两个 varray 类型,第一个可以保存 varchar 类型的 10 个元素,第二个可以保存 integer 类型的 10 个元素。

未初始化的 varray 变量是 null 集合。您必须初始化它,要么使它为空,要么给它分配一个非空值。


是时候举个例子了!

在下面的程序中,我们使用了 varray:

DECLARE 
   type snamesarray IS VARRAY(5) OF VARCHAR2(10); 
   type smarks IS VARRAY(5) OF INTEGER; 
BEGIN 
   snames namesarray := namesarray('John', 'Adam', 'Elly', 'Kate', 'Ron'); 
   marks smarks := smarks(42, 88, 62, 89, 97); 
   no_of_students := snames.count; 
   dbms_output.put_line('Total '|| no_of_students || ' Students'); 
   FOR i in 1 .. no_of_students LOOP 
      dbms_output.put_line('Student: ' || snames(i) || ' 
      Marks: ' || marks(i)); 
   END LOOP; 
END; 
/

共 5 名学生学生:约翰·马克斯:42 学生:亚当·马克斯:88 学生:艾莉·马克斯:62 学生:凯特·马克斯:89 学生:罗恩·马克斯:97 PL/SQL 程序成功完成。

正如您在上面的例子中看到的,我们已经声明了两种 varray 类型,一种用于存储学生姓名,另一种用于存储学生分数。

然后我们在我们的 PL/SQL 块中使用它们来存储学生姓名和学生标记。



PL/SQL 中的存储过程和函数

原文:https://www.studytonight.com/plsql/plsql-procedure-and-function

在本教程中,我们将通过示例介绍 PL/SQL 中存储过程和函数的概念。

存储过程和函数都可以定义为一组逻辑编写的语句,存储在数据库中,并在调用时执行,以执行特定的任务。

函数和存储过程都有一个唯一命名的代码块,该代码块被编译并存储在数据库中。

创建的任何存储过程或函数,除非被调用,否则仍然没有用。因此,在创建存储过程或函数之后,有必要从另一个 PL/SQL 块调用该存储过程或函数,以便达到创建它的目的。


创建存储过程或函数

每当存储过程或函数的代码块被写入时,它们就会被 oracle 引擎自动编译。在编译过程中,如果出现任何错误,我们会在屏幕上看到一条消息,说创建的过程或函数有编译错误,但实际错误不会显示。

为了找出编译错误,可以执行以下语句:

SELECT * from USER_ERRORS;

一旦被编译,它就被 oracle 引擎作为一个数据库对象存储在数据库中。

PL/SQL 中存储过程或函数的代码块由以下三部分组成:

  • 声明部分:在该部分中,声明了将由过程或函数使用的变量、常数、光标或异常。
  • 可执行部分:在这一部分中,编写了创建的过程或函数的定义。本节还包含赋值、控制执行和操作数据的 SQL 或 PL/SQL 语句。
  • 异常处理部分 : 在该部分中,编写了在执行以可执行部分编写的代码时可能出现的预期异常。此部分是可选的。

存储过程或函数的优势

以下是存储过程和函数在 PL/SQL 中的一些优点:

1。提高数据库性能

  • 编译由 oracle 引擎自动完成。
  • 每当过程或函数的调用完成时,oracle 引擎会将编译后的代码加载到一个名为系统全局区域(SGA)的内存区域,这样执行速度会更快。

2。提供可重用性并避免冗余

  • 过程或函数的同一代码块可以被调用任意次来处理多个数据。
  • 由于这种原因,代码的行数不能重复编写。

3。保持完整性

  • 诚信意味着准确。过程或函数的使用确保了完整性,因为它们被 oracle 引擎存储为数据库对象。

4。维护安全

  • 使用存储过程或函数有助于维护数据库的安全性,因为可以通过向用户授予访问/权限来控制对它们的访问和使用,而更改、编辑或操作数据库的权限可能不会授予用户。

5。节省内存

  • 存储过程或函数具有共享内存。因此,它节省了内存,因为一个过程或一个函数的单个副本可以由任何数量的具有访问权限的用户加载执行。

存储过程和函数的区别

下面我们列出了 PL/SQL 中存储过程和函数之间的一些区别:

| 存储过程 | 功能 |
| 可能会也可能不会向程序的调用部分返回值。 | 向程序的调用部分返回一个值。 |
| 使用输入、输出、输入输出参数。 | 仅使用输入参数。 |
| 使用“输出”参数返回值。 | 使用“RETURN”返回一个值。 |
| 如果在调用该值后将返回该值,则不指定该值的数据类型。 | 必须指定对其进行调用后要返回的值的数据类型。 |
| 不能从代码的函数块中调用。 | 可以从程序代码块中调用。 |


创建存储过程的语法

下面是在 oracle 中创建存储过程的基本语法:

CREATE OR REPLACE PROCEDURE <procedure_name> 
(<variable_name>IN/OUT/IN OUT <datatype>,
   <variable_name>IN/OUT/IN OUT <datatype>,...) IS/AS
variable/constant declaration;
BEGIN
	-- PL/SQL subprogram body;
EXCEPTION
	-- Exception Handling block ;
END <procedure_name>; 

让我们理解上面的代码,

  • 过程名是过程名,变量名是存储过程中使用的变量的变量名。
  • CREATE or REPLACE PROCEDURE是用于指定要创建的过程的名称的关键字。
  • BEGINEXCEPTIONEND是用于指示正在创建的过程的不同部分的关键词。
  • 输入/输出/输入输出是参数模式。
  • 模式中的指的是只读模式,该模式用于变量,通过该变量它将接受来自用户的值。这是默认的参数模式。
  • 输出模式是指只写模式,用于将值返回给用户的变量。
  • 输入输出模式是指读写模式,该模式用于变量,该变量要么接受用户的值,要么将该值返回给用户。
  • 最后,<procedure_name>是可选写的,可以简单使用END语句结束过程定义。</procedure_name>

是时候举个例子了!

在下面的代码示例中,我们创建了一个简单的程序来演示如何使用存储过程来添加两个数字:

set serveroutput on;

CREATE OR REPACE PROCEDURE Sum(a IN number, b IN number) IS
c number; 
BEGIN
	c := a+b;
	dbms_output.put_line('Sum of two nos= '|| c);
END Sum;

已创建过程。

为了调用创建的过程,将执行以下代码:

set serveroutput on;

DECLARE
	x number;
	y number;
BEGIN
	x := &x;
	y := &y;
	Sum(x,y);
END;

输入 x: 10 的值输入 y: 20 的值两个数之和= 30 PL/SQL 过程已成功创建。


在 PL/SQL 中创建函数的语法

既然我们知道了如何创建存储过程,以及如何在另一个 PL/SQL 代码块中使用它们,那么是时候了解如何在 PL/SQL 中创建函数了。

CREATE OR REPLACE FUNCTION <function_name>
(<variable_name> IN <datatype>,
<variable_name> IN <datatype>,...)
RETURN <datatype> IS/AS
variable/constant declaration;
BEGIN
	-- PL/SQL subprogram body;
EXCEPTION
	-- Exception Handling block ;
END <function_name>; 

让我们理解上面的代码,

  • 函数名用于定义函数名,变量名是函数中使用的变量的变量名。
  • CREATE or REPLACE FUNCTION是用于指定要创建的函数的名称的关键字。
  • 模式中的指的是只读模式,该模式用于变量,通过该变量它将接受来自用户的值。这是默认的参数模式。
  • RETURN是一个关键字,后跟一个数据类型,指定函数将返回的值的数据类型。

上述代码的大部分类似于用于定义存储过程的代码。


是时候举个例子了!

在下面的代码中,我们有一个程序来演示如何使用函数将两个数字相加。

set serveroutput on;

CREATE OR REPLACE FUNCTION Sum(a IN number, b IN number) RETURN Number IS
c number;
BEGIN
	c := a+b;
	RETURN c;
END; 

创建的函数

为了调用函数Sum,将执行以下代码:

set serveroutput on;

DECLARE
	no1 number;
	no2 number;
	result number;
BEGIN
	no1 := &no1;
	no2 := &no2;
	result := Sum(no1,no2);
dbms_output.put_line(‘Sum of two nos=’||result);
END;

输入 no1:5 的值输入 no2:5 的值两个 no 之和=10 PL/SQL 过程已成功创建。

有了这些,现在我们知道了如何在 PL/SQL 中定义和使用存储过程,以及如何在 PL/SQL 中定义和使用函数。



高级

PL/SQL 中的游标

原文:https://www.studytonight.com/plsql/plsql-cursor

在本教程中,我们将学习 PL/SQL 中的游标,它只不过是指向 oracle 引擎的工作区或上下文区的指针。

光标是指向工作区或上下文区的指针,由 oracle 引擎用于执行 SQL 语句。这样的工作区是 oracle 引擎专用于 SQL 操作的。

当 oracle 引擎执行一个 SQL 语句时,返回的数据行存储在游标中,称为活动数据集。并且游标占用了保存活动数据集中的行数所需的内存大小。

包含从表中检索的值的游标由 oracle engine 在主内存的预定义区域中打开。该数据然后通过网络传输到客户端机器。


PL/SQL 中游标的类型

根据创建和使用光标的条件,光标可以分为两种类型:

NaN. 隐式光标
NaN. 显式光标

隐式光标

在执行任何类似INSERTUPDATEDELETE的 DML(数据操作语言)查询时,由 Oracle 引擎自动创建、维护和关闭的游标称为隐式游标。

隐式游标由 Oracle 控制,程序员不能访问它的信息。

当执行 DML 语句时,会创建一个隐式游标并附加到它上面。

显式光标

为了执行任何返回多行的SELECT查询,必须由程序通过 PL/SQL 代码创建、维护和关闭的游标称为显式游标。

它是一个在 PL/SQL 块的Declare部分声明的用户定义的光标,用于其可执行部分。


使用显式光标

要定义光标,需要遵循以下步骤:

  • 声明光标

    这是在 PL/SQL 代码的声明部分通过编写检索数据进行处理的 SQL 语句来完成的。

    Syntax:

    CURSOR <cursor_name> IS <SELECT query>;
    

    例如,如果我们有用户表,该表具有列 id名称电子邮件,那么为了执行SELECT查询,我们可以这样声明光标:

    CURSOR c_users IS 
    	SELECT id, name, email FROM users;
    
  • 打开光标

    这是在 PL/SQL 代码的开始部分完成的。通过打开游标,为游标分配了获取记录的内存。

    Syntax:

    OPEN <cursor_name>;
    

    对于上面声明的c_users光标,它将是:

    OPEN c_users;
    
  • 获取光标

    要一次一行地将光标中的数据提取到内存变量中,我们使用FETCH命令。

    语法:

     fetch <cursor_name> into <list_of_variables>;
    
  • 要检查光标是否打开,我们使用光标的%ISOPEN属性。

    语法:

    if  <cursor_name> %ISOPEN
    
  • 确定提取是否成功。这可以通过使用FOUNDNOT FOUND属性来实现,因为如果 fetch 命令未能从游标中检索到任何行,则它会将“发现”设置为 false,而不是“发现”为 true。

  • 为了处理存储在内存变量中的数据,我们需要一个循环(我们稍后会谈到这一点)。

  • 处理完成后,使用 Exit 语句退出循环。

  • 然后,使用CLOSE命令关闭光标。
    Syntax:

CLOSE cursorname;

光标属性

要使用隐式或显式游标,可以使用以下属性:

| 属性名 | 描述 |
| %ISOPEN | 如果光标打开,它返回一个布尔值否则它返回布尔值 |
| %FOUND | 如果光标提取的记录成功,则返回布尔值,否则返回布尔值 |
| %NOTFOUND | 如果光标提取的记录不成功,则返回布尔值,否则返回布尔值 |
| %ROWCOUNT | 它返回受 PL/SQL 语句影响的行数 |


是时候举个例子了!

最后,让我们看看一个光标在行动。下面我们有一个 4 列的学生表,即rollinoSNAMEAGECOURSE

| 滚装船 | SNAME | 年龄 | 课程 |
| Eleven | 安奴 | Twenty | 平衡计分卡 |
| Twelve | 阿莎 | Twenty-one | 商学士 |
| Thirteen | 阿坡 | Eighteen | 喹啉甲酸 |
| Fourteen | 男性 | Twenty | 喹啉甲酸 |
| Fifteen | 波动 | Nineteen | BBA |

上表学生将在下面的程序中使用,我们将使用SELECT查询获取所有学生的姓名,将其存储在光标中,然后围绕光标循环打印姓名。

DECLARE
	CURSOR student_cursor IS SELECT sname FROM Student ;
	snm Student.sname %type;
BEGIN
	OPEN student_cursor;
	IF student_cursor%ISOPEN FALSE then
		dbms_output.put_line('Cannot open cursor');
	ELSE
		LOOP
			FETCH student_cursor INTO snm;
			IF student_cursor%NOTFOUND then
				Exit;
			END IF;
			dbms_ output.put_line('' ||snm);
		END LOOP;
		dbms_output.put_line('Total Records: ' ||student_cursor%rowcount);
	CLOSE student_cursor;
END;

Anu Asha Arpit Chetan Nihal 总记录:5 PL/SQL 程序成功完成。

在上面的程序中,

  • 我们使用了一个名为student_cursor的光标。
  • 输出显示学生的姓名以及找到的记录总数。

用于循环的光标

游标FOR LOOP是一个用于游标的循环,当存储在游标中的所有数据被迭代时,它会自动检查行数并退出循环。用于循环的光标会自动执行以下操作:

  • 隐式声明其循环索引为%rowtype记录
  • 打开光标
  • 为每次迭代从游标中检索记录
  • 处理完所有记录后关闭光标。
  • 也可以使用EXITGOTO语句关闭光标。

Syntax:

FOR variable_name IN cursor_name LOOP
	-- Executable statements
END LOOP; 

显示光标用于循环的示例

下面我们有一个简单的 PL/SQL 代码块,展示了循环游标的使用:

DECLARE
	CURSOR student_cursor IS SELECT sname FROM Student;
BEGIN
	FOR snm IN student_cursor LOOP	
		dbms_output.put_line('' || snm);
	END LOOP;
END; 

Anu Asha Arpit Chetan Nihal PL/SQL 程序成功完成。

在上面的程序中,

  • 使用名为student_cursor的光标。
  • 输出显示学生的姓名。

什么是参数化光标?

参数化游标是一种带有参数的游标,它允许我们使用包含变量的条件创建动态 SQL 查询。

这里我们有参数化游标声明的语法:

CURSOR cursor_name (variable_name Datatype) IS <SELECT statement...>;

声明参数化游标后,当我们打开它时,我们必须提供参数化游标中要使用的值,如下所示:

OPEN cursor_name(value/variable/expression);

让我们举一个例子来演示参数化游标的使用:

set serveroutput on;

DECLARE
	CURSOR showRec(sno student.rollno%type) IS SELECT sname, course FROM student WHERE rollno=sno;
	a  student.sname%type;
	b  student.course%type;
	c  student.rollno%type;
BEGIN
    d := &rollno;
	OPEN showRec(d);
		IF showRec%Isopen = FALSE then
			dbms_output.put_line('Cannot open Cursor');
		ELSE
			LOOP
				FETCH showRec into a,b;
				EXIT WHEN showRec%NOTFOUND;
				dbms_output.put_line(a|| '' ||b);
			END LOOP;
		End IF;
	CLOSE showRec;
END;

输入 d:12-| SNAME | COURSE | = = = = = = = = = = = = = = = = = = = = = = = = = = = = = | Asha | BCOM |-PL/SQL 过程已成功完成。

在上面的程序中,

  • 使用名为student_cursor的光标。
  • 输出显示学生的姓名课程,该学生的是在程序执行期间由用户输入的。


PL/SQL 中的异常处理

原文:https://www.studytonight.com/plsql/plsql-exception-handling

异常是在执行 PL/SQL 代码块期间发生的运行时错误或意外事件。

oracle 引擎是第一个识别这种异常的引擎,它会立即尝试通过默认的异常处理程序来解决它。

默认异常处理程序是内存中预定义的代码块,用于对异常采取适当的操作。

异常处理可以在 PL/SQL 程序代码块的异常部分完成。

以下是它的语法:

DECLARE
	-- Declaration statements;
BEGIN
	-- SQL statements;
	-- Procedural statements;
EXCEPTION
	-- Exception handling statements;
END;

有两种类型的例外:

  1. 系统(预定义)例外
  2. 用户定义的例外

让我们逐一介绍这两种类型的异常。


系统(预定义)例外

为了处理运行 PL/SQL 代码时出现的常见异常,oracle 中有两种类型的异常处理程序:

  • 命名异常处理程序
  • 编号异常处理程序

命名异常处理

这些异常是 oracle 为最常见的异常预先定义的名称。

以下是处理命名异常的语法:

EXCEPTION
	WHEN <exception_name> THEN
		-- take action 

默认情况下,有许多预定义的命名异常可用。下表中几乎没有显示它们及其含义:

| 命名异常 | 意义 |
| LOGIN_DENIED | 当连接到 Oracle 时给出无效的用户名或密码时发生。 |
| TOO_MANY_ROWS | 当 select 语句返回多行时发生。 |
| VALUE_ERROR | 当用户给出无效的数据类型或大小时发生。 |
| NO_DATA_FOUND | 当找不到记录时发生。 |
| DUP_VAL_ON_INDEX | 当对某一列应用了唯一约束,并且执行“插入”或“更新”导致为该列创建重复记录时发生。 |
| PROGRAM_ERROR | 当程序中出现内部错误时发生。 |
| ZERO_DIVIDE | 当任何变量值除以零时发生。 |

时间为例!

下面我们有一个简单的 PL/SQL 代码块,用来演示命名异常处理程序的使用,

set serveroutput on;

DECLARE
	a int;
	b int;
	c int;
BEGIN
	a := &a;
	b := &b;
	c := a/b;
	dbms_output.put_line('RESULT=' || c);
EXCEPTION
	when ZERO_DIVIDE then
		dbms_output.put_line('Division by 0 is not possible');
END;

输入 a:10 的值输入 b:0 的值除以 0 是不可能的 PL/SQL 过程成功完成。

编号异常处理

在甲骨文中,一些预定义的异常以四个整数的形式编号,前面有一个连字符符号。为了处理这样的异常,我们应该在使用它们之前给它们指定一个名称。

这可以通过使用 Pragma 异常技术来实现,在该技术中,编号异常处理程序绑定到一个名称。为此,我们在 PL/SQL 程序中使用一个关键字,并使用以下语法编写一个将名称绑定到编号异常的语句,该语句写在程序的 DECLARE 部分:

pragma exception_init(exception_name, exception _number);

其中,pragma exception_init(大小写无关紧要)是表示 Pragma 异常技术的关键字,有两个参数:

  • 异常 _ 名称,这是一个用户定义的名称,如果发生了预定义的编号异常,则赋予该名称。
  • exception_number ,是甲骨文分配给该异常的编号。

时间为例!

下面我们有一个表格,里面有学生的数据。

| 滚装船 | SNAME | 年龄 | 课程 |
| Eleven | 安奴 | Twenty | 平衡计分卡 |
| Twelve | 阿莎 | Twenty-one | 商学士 |
| Thirteen | 阿坡 | Eighteen | 喹啉甲酸 |
| Fourteen | 男性 | Twenty | 喹啉甲酸 |
| Fifteen | 波动 | Nineteen | BBA |

在下面的 PL/SQL 程序中,我们将使用上表学生演示编号异常的使用,

set serveroutput on;

DECLARE
	sno student.rollno%type;
	snm student.sname%type;
	s_age student.age%type;
	cr student.course%type;
	-- Exception name declared below
	already_exist EXCEPTION;
	-- pragma statement to provide name to numbered exception
	pragma exception_init(already_exist, -1);
BEGIN
	sno:=&rollno;
	snm:='&sname';
	s_age:=&age;
	cr:='&course';
	INSERT into student values(sno, snm, s_age, cr);
	dbms_output.put_line('Record inserted');
	EXCEPTION
		WHEN already_exist THEN
			dbms_output.put_line('Record already exist');
END;

输入 sno:11 的值输入 snm:heena 的值输入 s_age:20 的值输入 cr:bsc 记录的值已存在 PL/SQL 过程已成功完成。

在上述程序中,只要违反了主键概念(记录应唯一且不为空),oracle 就会通过 -1 生成一个编号异常,这就是为什么在执行上述程序期间用户输入的rollino11 的原因。程序的异常部分开始运行,并在用户记录已经存在之前显示消息。

使用程序声明部分中的pragma关键字已经存在字符串被映射到一个编号的异常 -1


用户定义的异常

在任何程序中,都有可能出现一些 oracle 不认为是异常的错误。在这种情况下,程序员可以在编写代码时定义异常。这种类型的异常称为用户定义异常。

用户定义的异常通常被定义为处理特殊情况,在这种情况下,由于我们的代码逻辑,我们的代码可以生成异常。

此外,在代码逻辑中,您可以使用RAISE关键字显式指定生成异常,然后使用EXCEPTION块处理它。

下面是它的语法,

DECLARE
	<exception name> EXCEPTION
BEGIN
	<sql sentence>
	If <test_condition> THEN 
		RAISE <exception_name>;
	END IF;
	EXCEPTION
		WHEN <exception_name> THEN
			-- some action
END;

让我们举个例子来理解如何使用用户定义的异常。下面我们有一个简单的例子,

| 滚装船 | SNAME | 总计 _ 课程 |
| Eleven | 安奴 | Two |
| Twelve | 阿莎 | one |
| Thirteen | 阿坡 | three |
| Fourteen | 男性 | one |

在下面的 PL/SQL 程序中,我们将使用上表学生演示用户定义异常的使用,

set serveroutput on;

DECLARE
	sno student.rollno%type;
	snm student.sname%type;
	crno student.total_course%type;
	invalid_total EXCEPTION;
BEGIN
	sno := &rollno;
	snm := '&sname';
	crno:=total_courses;
	IF (crno > 3) THEN 
		RAISE invalid_total;
	END IF;
	INSERT into student values(sno, snm, crno);
	EXCEPTION
		WHEN invalid_total THEN
			dbms_output.put_line('Total number of courses cannot be more than 3');
END;

输入 sno:15 的值输入 snm:Akash 的值输入 crno:5 的值课程总数不能超过 3 成功完成的 PL/SQL 过程。

在上面的程序中,

使用名为 invalid_total 的自定义异常,该异常在课程总数大于 3(一个学生最多可注册 3 门课程)时生成

这样我们就没有例外了。


PL/SQL 中的触发器

原文:https://www.studytonight.com/plsql/plsql-triggers

oracle 中的触发器是 PL/SQL 代码块,oracle 引擎可以根据某些操作或事件自动执行这些代码块。

这些事件可以是:

  • 语句(创建、更改、删除、截断)
  • DML 语句(插入、选择、更新、删除)
  • 数据库操作,如连接或断开与 oracle 的连接(登录、注销、关机)

满足特定条件时,oracle 引擎会自动重复调用触发器。

触发器可以根据需要激活或停用。

如果触发器被激活,则由 oracle 引擎隐式执行;如果触发器被停用,则由 oracle 引擎显式执行。


触发器的使用

这里我们提到了一些使用触发器非常有用的用例:

  • 维护复杂的约束,通过常规的约束(如主要的、外来的、独特的等)应用技术,这不是不可能就是非常困难。
  • 记录在桌面上所做的更改。
  • 自动生成主键值。
  • 防止无效交易发生。
  • 向数据库授予授权并提供安全性。
  • 强制引用完整性。

触发器的一部分

每当创建触发器时,它都包含以下三个连续部分:

  • 触发事件或语句:触发事件发生的语句称为触发事件或语句。这样的语句可以是 DDL 语句、DML 语句或任何数据库操作,执行这些语句会引发触发器。
  • 触发限制:对触发器施加的条件或任何限制称为触发限制。因此,如果这样的条件是,则触发发生,否则不发生。
  • 触发动作:包含当触发发生时要执行的可执行语句的主体,该可执行语句与触发语句一起执行,并且在将触发限制评估为真时被称为触发动作。

触发器的类型

上图清楚地表明,触发器可以分为三类:

  1. 电平触发器
  2. 事件触发器
  3. 定时触发器

进一步分为不同的部分。

电平触发器

有两种不同类型的级别触发器,它们是:

  1. 行级别触发
    • 它会为执行 DML 语句(如插入、更新、删除等)而受到影响的每一条记录触发。
    • 它总是在触发语句中使用FOR EACH ROW 子句。
  2. 语句级别触发
    • 它对执行的每个语句触发一次。

事件触发器

有 3 种不同类型的事件触发器,它们是:

  1. 驾驶员侧车门开启事件触发器
    • 它会随着每个 DDL 语句的执行而触发(CREATE、ALTER、DROP、TRUNCATE)。
  2. DML 事件触发器
    • 它在执行每个 DML 语句(插入、更新、删除)时触发。
  3. 数据库事件触发器
    • 它随着每个数据库操作的执行而触发,这些操作可以是登录、注销、关机、服务器错误等。

定时触发器

有两种不同类型的定时触发器,它们是:

  1. 触发前
    • 它在执行 DML 语句之前激发。
    • 触发语句可以执行,也可以不执行,这取决于 before 条件块。
  2. 触发后
    • 它在执行 DML 语句后激发。

创建触发器的语法

以下是创建触发器的语法:

CREATE OR REPLACE TRIGGER <trigger_name>
BEFORE/AFTER/INSTEAD OF
	INSERT/DELETE/UPDATE ON <table_name>
REFERENCING (OLD AS O, NEW AS N)
	FOR EACH ROW WHEN (test_condition)
DECLARE
	-- Variable declaration;
BEGIN
	-- Executable statements;
EXCEPTION
	-- Error handling statements;
END <trigger_name>;
END; 

哪里,

CREATE OR REPLACE TRIGGER是用于创建触发器的关键字, < trigger_name > 是用户定义的,其中触发器可以被赋予名称。

BEFORE/AFTER/INSTEAD OF指定触发发生的时间。创建视图时使用INSTEAD OF

插入/更新/删除指定 DML 语句。

<表名> 指定要应用 DML 语句的表的名称。

REFERENCING是用于为 DML 语句提供新旧值引用的关键字。

FOR EACH ROW是用于指定行级跳跳虎的子句。

WHEN是用于指定要应用的条件的子句,仅适用于行级触发器。

DECLAREBEGINEXCEPTIONEND分别是 PL/SQL 代码块中包含变量声明、可执行语句、错误处理语句和标记 PL/SQL 块结束的不同部分,其中 DECLARE 和 EXCEPTION 部分是可选的。


是时候举个例子了!

下面我们有一个简单的程序来演示触发器在 PL/SQL 代码块中的使用。

CREATE OR REPLACE TRIGGER CheckAge
BEFORE
INSERT OR UPDATE ON student
FOR EACH ROW
BEGIN
	IF :new.Age>30 THEN
		raise_application_error(-20001, 'Age should not be greater than 30');
	END IF;
END; 

触发器已创建。

下面是学生表,

| 滚装船 | SNAME | 年龄 | 课程 |
| Eleven | 安奴 | Twenty | 平衡计分卡 |
| Twelve | 阿莎 | Twenty-one | 商学士 |
| Thirteen | 阿坡 | Eighteen | 喹啉甲酸 |
| Fourteen | 男性 | Twenty | 喹啉甲酸 |
| Fifteen | 波动 | Nineteen | BBA |

在初始化触发器CheckAge之后,每当我们在上面的表 STUDENT 中插入任何新值或更新现有值时,我们的触发器都会在执行INSERTUPDATE语句之前检查年龄,并根据触发限制或条件的结果执行该语句。

让我们举几个例子来试着理解这一点,

例 1:

INSERT into STUDENT values(16, 'Saina', 32, 'BCOM');

年龄不应大于 30 岁

例 2:

INSERT into STUDENT values(17, 'Anna', 22, 'BCOM');

创建了 1 行

例 3:

UPDATE STUDENT set age=31 where ROLLNO=12; 

年龄不应大于 30 岁

例 4:

 UPDATE STUDENT set age=23 where ROLLNO=12; 

更新了 1 行。


PL/SQL 中的包

原文:https://www.studytonight.com/plsql/plsql-packages

包是一种将子程序,如程序函数、异常或光标逻辑存储到单个公共单元中的方式。

包可以定义为一个被编译并存储在数据库中的 oracle 对象。

一旦它被编译并存储在数据库中,它就可以被对 Oracle 数据库具有可执行权限的所有数据库用户使用。

包装的成分

包有两个基本组件:

  • 规格:是包装的申报部分
  • 正文:是一个包的定义部分。

使用软件包的好处

以下是 PL/SQL 中包的一些好处:

  1. REUSABILITY

    每当创建包时,它都会被编译并存储在数据库中。因此,您只需编写一次代码,它就可以被其他应用程序重用。

  2. OVERLOADING

    在一个同名的包中可以创建两个或多个 >过程或函数。

  3. CREATING MODULES

    一个大的应用程序可以通过简单地创建模块(或子程序)来创建,这些模块定义清晰且易于工作。

  4. IMPROVES PERFORMANCE

    包代码在第一次调用自身时被加载到 Oracle 的 SGA(系统全局区域)中,因此其他后续调用将非常快速地工作。

  5. GLOBAL DECLARATION

    如果对象(过程、函数、变量、常量、异常光标等)在一个包中全局声明,则在需要时可以很容易地使用它们。


如何创建一个 PL/SQL 包?

以下是在 PL/SQL 代码块中声明和使用包的步骤:

第一步:包装规范或声明

它主要包括以下内容:

  • 包名。
  • 变量/常量/游标/过程/函数/异常声明。
  • 该声明对包是全局的。

以下是语法:

CREATE OR REPLACE PACKAGE <package_name> IS/AS
	FUNCTION <function_name> (<list of arguments>) 
	RETURN <datatype>;
	PROCEDURE <procedure_name> (<list of arguments>);
	-- code statements
END <package_name>; 

哪里,

CREATE OR REPLACE PACKAGE是用于创建包的关键字

FUNCTIONPROCEDURE是创建包时用于声明函数和过程的关键字。

<包 _ 名称><功能 _ 名称><程序 _ 名称> 均为自定义名称。

IS/AS是用于申报包的关键字。

RETURN是指定由声明的函数返回的值的关键字。

步骤 2:包装主体

它主要包括以下内容:

  • 它包含在包规范中声明的过程、函数或游标的定义。
  • 它包含子程序体,子程序体包含已为其创建包的可执行语句

以下是语法:

CREATE  OR REPLACE PACKAGE BODY <package_name> IS/AS
FUNCTION <function_name> (<list of arguments>) RETURN <datatype>IS/AS
	-- local variable declaration;
	BEGIN
		-- executable  statements;
	EXCEPTION
		-- error handling statements;
END <function_name>;

PROCEDURE <procedure_name> (<list of arguments>)IS/AS
	-- local variable declaration;
	BEGIN
		-- executable statements;
	EXCEPTION
		-- error handling statements;
	END <procedure_name>;
END <package_name>;

哪里,

CREATE OR REPLACE PACKAGE BODY是用于创建带有正文的包的关键字。

FUNCTIONPROCEDURE是创建包时用于定义功能和过程的关键字。

<包 _ 名称><功能 _ 名称><程序 _ 名称> 均为用户自定义。

IS/AS是用于定义包体、功能和过程的关键字。

RETURN是指定由定义的函数返回的值的关键字。

DECLAREBEGINEXCEPTIONEND分别是 PL/SQL 代码块中包含变量声明、可执行语句、错误处理语句和标记 PL/SQL 块结束的不同部分,其中 DECLARE 和 EXCEPTION 部分是可选的。

注意:创建包只是定义它,要使用它我们必须使用包对象引用它。

以下是引用包对象的语法:

Packagename.objectname;

对象可以是函数、过程、游标、异常,它们已在包规范中声明并在包主体中定义,要访问它们的可执行语句,请使用上述语法。

是时候举个例子了!

我们有如下指定的学生表:

| 滚装船 | SNAME | 年龄 | 课程 |
| Eleven | 安奴 | Twenty | 平衡计分卡 |
| Twelve | 阿莎 | Twenty-one | 商学士 |
| Thirteen | 阿坡 | Eighteen | 喹啉甲酸 |
| Fourteen | 男性 | Twenty | 喹啉甲酸 |
| Fifteen | 波动 | Nineteen | BBA |

让我们编写一个简单的程序来演示包在 PL/SQL 中的使用。

包规格的 PL/SQL 代码:

CREATE OR REPLACE PACKAGE pkg_student IS
	PROCEDURE  updateRecord(sno student.rollno%type);
	FUNCTION deleteRecord(snm student.sname%type)
		RETURN boolean;
END pkg_student; 

已创建包

包体 PL/SQL 代码:

 set serveroutput on;
CREATE OR REPLACE PACKAGE BODY pkg_student IS
	PROCEDURE updateRecord(sno student.rollno%type) IS
		BEGIN
			Update student set age=23 where rollno=sno;
			IF  SQL%FOUND THEN
				dbms_output.put_line('RECORD UPDATED');
			ELSE
				dbms_output.put_line('RECORD NOT FOUND');
			END IF;
		END updateRecord;

	FUNCTION deleteRecord(snm student.sname%type) RETURN boolean IS
		BEGIN
			Delete from student where sname=snm;
			RETURN SQL%FOUND;
		END deleteRecord;
END pkg_student;

已创建包主体

现在让我们编写 PL/SQL 代码,用于调用包中使用的过程和函数。

 set serveroutput on;
DECLARE
	sno student.rollno%type;
	s_age student.age%type;
	snm student.sname%type;
BEGIN
	sno := &sno;
	snm := &snm
	pkg_student.updateRecord(sno);
	IF pkg_student.deleteRecord(snm) THEN
		dbms_output.put_line('RECORD DELETED');
	ELSE
		dbms_output.put_line('RECORD NOT FOUND');
	END IF;
END;

输入 sno: 12 的值输入 snm: Neha 记录更新记录未找到 PL/SQL 过程成功完成的值。

注意:如果创建的包规范或包主体存在编译错误,则屏幕上会显示以下警告消息:

警告:创建的包体有编译错误。

在这种情况下,可以通过执行以下语句来查看错误:

 SHOW ERRORS;

在下一个教程中,我们将介绍 PL/SQL 中的事务。



PL/SQL 事务

原文:https://www.studytonight.com/plsql/plsql-transactions

事务是通过在 PL/SQL 代码块中执行 SQL 语句而执行的一系列操作,其中适用以下规则:

  1. 如果我们在一个事务中有一组语句,那么完整的语句集将作为一个块执行,其中如果一个语句失败了,所有先前成功的语句执行的影响也将恢复。
  2. 在事务中,要么所有语句都成功执行,要么都不执行。
  3. 事务的范围通过使用 COMMIT 和 ROLLBACK 命令来定义

使用 PL/SQL 事务

它有开始也有结束。

每当遇到第一条 SQL 语句(特别是 DML 命令INSERTUPDATEDELETESELECT)时,事务开始,当执行COMMITROLLBACK命令时,事务结束。

使用 COMMIT

提交命令在每个 DML 命令之后执行,因为它们不像 DDL 命令那样自动保存或提交。这样,commit 命令会永久更改数据库中的数据。

以下是语法:

Commit;

注意:默认情况下,DML 命令的自动提交关闭。可以使用以下命令设置 DML 命令的自动提交:

set autocommit on;
-- and to turn it off
set autocommit off;

使用回滚

回滚意味着撤销。每当执行回滚命令时,它将结束事务并撤消事务期间所做的所有更改。回滚可以应用于那些未提交的事务。

如果回滚命令在提交命令之后执行,它将不会有任何影响,因为在这种情况下,提交命令将使事务中所做的更改永久化。

以下是语法:

Rollback [to savepoint <savepointname >];

哪里,

保存点是一个可选参数,用于将事务部分回滚到某个指定点。

保存点名称是事务期间创建的保存点的名称,由用户定义。

使用保存点

对于较长的事务,保存点非常有用,因为它将较长的事务分成较小的部分,并将事务的某些点标记为检查点。

当我们想要回滚事务的特定部分,而不是将回滚应用于事务的不需要的部分或整个事务时,这很有用。

例如,如果一个完整的事务有 8 条 DML 语句,并且我们在 4 条语句之后创建了一个保存点,那么如果在执行第 6 条语句之后,由于某种原因,我们想要回滚第 4 条语句,那么我们可以很容易地做到这一点,并且事务可以从第 4 条语句开始再次执行。

以下是语法:

Savepoint  <savepointname>;

是时候举个例子了!

下面我们有一个 PL/SQL 程序来演示事务的执行,

set serveroutput on;

DECLARE
	rollno student.sno%type;
	snm student.sname%type;
	s_age student.age%type;
	s_cr student.course%type;
BEGIN
	rollno := &sno;
	snm := '&sname';
 	s_age := &age;
	s_cr := '&course';
	INSERT into student values(rollno,snm,age,course);
	dbms_output.put_line('One record inserted');
	COMMIT;
END; 

在 PL/SQL 块的上述代码中,数据库中有一个名为 STUDENT 的表,列 sno 为数字, sname 为 varchar2, age 为数字,课程为 varchar2。

在代码中,我们执行了INSERT语句,然后使用COMMIT语句将更改提交或永久保存到数据库中。

代替COMMIT语句,如果我们在那里使用ROLLBACK语句,那么即使INSERT语句执行成功,但是,在执行 PL/SQL 块之后,如果您将检查数据库中的 student 表,您将不会找到新的 Student 条目,因为我们执行了ROLLBACK语句,并且它回滚了更改。

带保存点和回滚的 PL/SQL 代码示例

让我们在上面的代码中添加两个 insert 语句,并在它们之间放置一个保存点,然后使用ROLLBACK命令恢复一个 insert 语句的更改。

set serveroutput on;

DECLARE
	rollno student.sno%type;
	snm student.sname%type;
	s_age student.age%type;
	s_cr student.course%type;
BEGIN
	rollno := &sno;
	snm := '&sname';
 	s_age := &age;
	s_cr := '&course';
	INSERT into student values(rollno,snm,age,course);
	dbms_output.put_line('One record inserted');
	COMMIT;
	-- adding savepoint
	SAVEPOINT savehere;
	-- second time asking user for input
	rollno := &sno;
	snm := '&sname';
 	s_age := &age;
	s_cr := '&course';
	INSERT into student values(rollno,snm,age,course);
	dbms_output.put_line('One record inserted');
	ROLLBACK [TO SAVEPOINT savehere];
END; 

执行上述代码后,我们将在 Student 表中创建一个条目,而第二个条目将被回滚。



PL/SQL 中的锁

原文:https://www.studytonight.com/plsql/locks-in-plsql

PL/SQL 中的锁是维护数据库数据完整性的一种方式。因为 oracle 是一个多用户平台,在这个平台上,数据库中使用的表充当多个用户同时共享的全局资源。

由于多个用户同时对数据进行并发处理,数据可能会变得不一致。因此,锁在维护并发控制方面起着重要的作用,确保数据库中存储数据的数据完整性。


PL/SQL:锁的类型

以下是 Oracle 中两种不同类型的锁定:

  1. 隐式锁定
  2. 显式锁定

隐式锁定

这是 oracle 引擎根据以下两个因素自动锁定数据库:

  1. 要应用的锁的类型。
  2. 要应用的锁定级别。

让我们逐一看看这两个因素:

1。要使用的锁的类型

根据对数据库执行的操作类型(读或写),有两种类型的锁。

| 锁的类型 | 描述 |
| 共享锁 |

  • Apply to the table that is viewing data, that is, reading the stored data.
  • Multiple shared locks can be applied to a table at the same time.
  • Used in the case of SELECT statement.

|
| 互锁 |

  • Apply to tables that are changing data (that is, writing data).
  • Only one exclusive lock can be placed at a time.
  • Used in the case of INSERT, UPDATE and DELETE statements.

|

2。要应用的锁定级别:

锁定可以在三个级别上完成:

  1. 行级:当使用WHERE子句在单行(或记录)的查询中应用条件时使用。
  2. 页面级:当使用WHERE子句对某组数据(某些记录)进行查询时,使用该条件。
  3. 表级:在使用WHERE子句对整个数据表(某些记录)进行查询时应用该条件时使用。

显式锁定

这是用户根据其授予的表权限对数据库进行的用户定义的锁定。这种类型的锁定覆盖了隐式锁定。显式锁定可以通过使用以下方法之一来完成:

  1. 挑选...对于更新语句

  2. 锁表语句

1。选择…更新声明:

以下是该语句的语法:

语法:

SELECT * FROM tablename WHERE condition For Update Nowait;

让我们举几个例子来看看,

假设两个客户端,客户端 X 和客户端 Y 在同一个数据库表 flight_detail 上执行事务

以下是客户端 X 运行的查询:

SELECT * from flight_detail where city='DELHI' For Update;

当执行上述SELECT语句时,oracle 引擎会自动锁定城市为德里的记录,并且只有当客户端 X 将执行COMMITROLLBACK命令时,才能释放该锁定。

现在让我们看看客户端 Y 运行的查询:

SELECT * from flight_detail where city='DELHI' For Update;

现在客户端 Y 对已经被客户端 X 的 oracle 引擎锁定的同一记录执行SELECT语句。因此在这种情况下,客户端 Y 必须等待直到客户端 X 通过执行COMMIT语句释放锁。

因此,为了克服不必要的等待时间NOWAIT选项可以用来通知 oracle 引擎记录已经被锁定,并且它可以终止语句。

所以如果客户端 Y 使用NOWAIT选项执行查询,

SELECT * from flight_detail where city='DELHI' For Update Nowait;

随着上述语句的执行,oracle 引擎在输出资源繁忙中显示消息。

注:

Select…For update 语句不能与组功能组运算符组运算符不同的子句一起使用。


锁表语句

我们还可以通过执行 Lock table 语句来获取表上的锁。

以下是语法:

LOCK TABLE tablename in lock mode WAIT/NOWAIT;

哪里,

锁定模式可以是以下模式之一:

  • EXCLUSIVE:允许对锁定的表进行查询。
  • SHARE:允许查询,但限制对表的更新。
  • ROW EXCLUSIVE:允许多用户并发访问表,但限制以独占或共享模式锁定表。
  • SHARE ROW EXCLUSIVE:允许查看整个表记录,但限制在共享模式下锁定表,也限制对表的 UPDATE。

WAIT表示 oracle 引擎将等待,直到资源自由可用。

NOWAIT表示 oracle 引擎不会等待资源可用,而是向用户显示消息资源正忙



posted @ 2024-10-24 18:15  绝不原创的飞龙  阅读(4)  评论(0编辑  收藏  举报