数据库。 讲义:简而言之,最重要的 目录
第 1 讲 引言 1. 数据库管理系统 数据库管理系统 (DBMS) 是允许: 1)永久存储任意大(但不是无限)量的数据; 2) 使用所谓的查询以一种或另一种方式提取和修改这些存储的数据; 3)创建新数据库,即描述逻辑数据结构并设置其结构,即提供编程接口; 4) 多个用户同时访问存储的数据(即提供对事务管理机制的访问)。 因此,本 数据库 是在管理系统控制下的数据集。 现在数据库管理系统是市场上最复杂的软件产品并构成了它的基础。 未来,计划将传统数据库管理系统与面向对象编程(OOP)和互联网技术相结合进行开发。 最初,DBMS 基于 分层的 и 网络数据模型,即只允许使用树和图结构。 在 1970 年的发展过程中,出现了 Codd 提出的数据库管理系统,基于 关系数据模型. 2.关系数据库 “关系”一词来自英文单词“relation”——“关系”。 在最一般的数学意义上(可以从经典的集合代数课程中记住) 态度 - 这是一套 R = {(x1,..., Xn) | X1 ∈一个1,...,Xn ∈ An}, 其中一个1,..., An 是形成笛卡尔积的集合。 这样, 比率R 是集合的笛卡尔积的一个子集:A1 x... x An : R⊆A 1 x... x An. 例如,考虑在有序数对集合 A 上的严格顺序“大于”和“小于”的二元关系 1 = A2 = {3, 4, 5}: R> = {(3, 4), (4, 5), (3, 5)} ⊂ A1 A2; R< = {(5, 4), (4, 3), (5, 3)} ⊂ A1 A2. 这些关系可以以表格的形式呈现。 比率“大于”>: 比率“小于”R<: 因此,我们看到在关系数据库中,各种各样的数据都以关系的形式组织起来,并且可以以表格的形式呈现。 需要注意的是,这两个关系 R> 和R.< 不等价,也就是说,这些关系对应的表不等价。 因此,关系数据库中的数据表示形式可以不同。 这种不同表征的可能性如何在我们的案例中体现出来? 关系 R> 和R.< - 这些是集合,集合是无序结构,这意味着在这些关系对应的表中,行可以相互交换。 但同时,这些集合的元素是有序集合,在我们的例子中 - 数字 3、4、5 的有序对,这意味着列不能互换。 因此,我们已经表明,以具有任意行顺序和固定列数的表的形式表示关系(在数学意义上)是一种可接受的、正确的关系表示形式。 但是如果我们考虑关系 R> 和R.< 从嵌入其中的信息的角度来看,它们显然是等价的。 因此,在关系数据库中,“关系”的概念与一般数学中的关系的含义略有不同。 即,它与以表格形式呈现的列排序无关。 取而代之的是,引入了所谓的“行-列标题”关系方案,即每列都有一个标题,之后它们可以自由交换。 这就是我们的 R 关系的样子> 和R.< 在关系数据库中。 严格的顺序关系(而不是关系 R>): 严格的顺序关系(而不是关系 R<): 两个表关系都有一个新的(在这种情况下,相同,因为通过引入额外的标题,我们消除了关系 R 之间的差异> 和R.<) 标题。 因此,我们看到,借助将必要的表头添加到表中这样一个简单的技巧,我们得出了这样一个事实,即关系 R> 和R.< 变得彼此等价。 因此,我们得出结论,一般数学和关系意义上的“关系”概念并不完全一致,它们并不完全相同。 目前,关系数据库管理系统构成了信息技术市场的基础。 进一步的研究正在朝着结合不同程度的关系模型的方向进行。 讲座 #2. 缺失数据 用于检测缺失数据的数据库管理系统中描述了两种类型的值:空(或 Empty-values)和 undefined(或 Null-values)。 在一些(主要是商业)文献中,Null 值有时被称为空值或空值,但这是不正确的。 空义和不定义的意义有着根本的不同,因此有必要仔细监控特定术语的使用上下文。 1.空值(Empty-values) 空值 只是某些定义明确的数据类型的许多可能值之一。 我们列出了最“自然”、最直接的 空值 (即我们可以在没有任何附加信息的情况下自行分配的空值): 1) 0(零)- 对于数值数据类型,null 值为空; 2) false(错误)- 是布尔数据类型的空值; 3) B'' - 可变长度字符串的空位字符串; 4) "" - 可变长度字符串的空字符串。 在上述情况下,您可以通过将现有值与为每种数据类型定义的空常量进行比较来确定值是否为空。 但是数据库管理系统,由于在其中实施的用于长期数据存储的方案,只能使用恒定长度的字符串。 因此,一个空的位串可以称为二进制零串。 或者由空格或任何其他控制字符组成的字符串是一个空字符串。 以下是一些恒定长度空字符串的示例: 1) B'0'; 2) B'000'; 3)''。 在这些情况下,如何判断字符串是否为空? 在数据库管理系统中,使用一个逻辑函数来测试是否为空,即谓词 IsEmpty(<表达式>),字面意思是“吃空”。 这个谓词通常内置在数据库管理系统中,可以应用于任何类型的表达式。 如果数据库管理系统中没有这样的谓词,那么您可以自己编写一个逻辑函数并将其包含在正在设计的数据库的对象列表中。 考虑另一个不太容易确定我们是否有空值的例子。 日期类型数据。 如果日期可以在 01.01.0100 的范围内变化,则该类型中的哪个值应被视为空值。 在 31.12.9999 年 XNUMX 月 XNUMX 日之前? 为此,在 DBMS 中引入了一个特殊名称,用于 空日期常量 {...},如果这个类型的值被写成:{DD. 毫米。 YY} 或 {YY. 毫米。 DD}。 使用此值,在检查值是否为空时会进行比较。 它被认为是这种类型表达式的定义明确的“完整”值,并且是可能的最小值。 使用数据库时,空值通常用作默认值或在缺少表达式值时使用。 2.未定义的值 (空值) 字 空 用来表示 未定义的值 在数据库中。 为了更好地理解哪些值被理解为 null,请考虑一个作为数据库片段的表: 因此, 未定义的值 или 空值 - 这是: 1) 未知,但通常,即适用值。 比如我们数据库中排名第一的Khairetdinov先生,无疑有一些护照数据(比如1980年出生的人,该国公民),但他们不为人所知,因此,他们没有被纳入数据库. 因此,Null 值将写入表的对应列; 2) 不适用值。 Karamazov 先生(我们数据库中的第 2 位)根本无法拥有任何护照数据,因为在创建此数据库或将数据输入其中时,他还是个孩子; 3)表格任何单元格的值,如果我们不能说它是否适用。 例如,在我们数据库中排名第三的科瓦连科先生不知道出生年份,因此我们无法确定他是否有护照数据。 因此,科瓦连科先生专用行中两个单元格的值将是空值(第一个 - 一般未知,第二个 - 作为性质未知的值)。 与任何其他数据类型一样,Null 值也具有一定的 性能. 我们列出了其中最重要的: 1)随着时间的推移,对 Null 值的理解可能会发生变化。 例如,对于 Karamazov 先生(我们数据库中的第 2 位)在 2014 年,即在达到成年年龄时,Null 值将变为某个特定的、明确定义的值; 2)空值可以赋给任何类型(数值、字符串、布尔值、日期、时间等)的变量或常量; 3)对以Null-values作为操作数的表达式进行任何操作的结果都是Null-value; 4) 上一条规则的一个例外是在吸收定律条件下的合取和析取运算(关于吸收定律的更多细节,参见第 4 讲第 2 段)。 3.空值和表达式求值的一般规则 让我们更多地谈谈对包含 Null 值的表达式的操作。 处理 Null 值的一般规则(即对 Null 值的运算结果为 Null 值)适用于以下操作: 1)算术; 2) 按位求反、合取和析取运算(吸收律除外); 3) 对字符串的操作(例如,concatenation - 字符串的串联); 4) 到比较运算(<, ≤, ≠, ≥, >)。 让我们举个例子。 作为应用以下操作的结果,将获得 Null 值: 3 + Null, 1/ Null, (Ivanov' + '' + Null) ≔ Null 在这里,我们不使用通常的相等性,而是使用 替代操作 "≔" 由于使用 Null 值的特殊性质。 在下文中,该字符也将用于类似情况,这意味着通配符右侧的表达式可以替换通配符左侧列表中的任何表达式。 Null 值的性质通常会导致某些表达式产生 Null 值而不是预期的 null,例如: (x - x), y * (x - x), x * 0 ≔ 当 x = Null 时为 Null。 事情是,当例如将值 x = Null 代入表达式 (x - x) 时,我们得到表达式 (Null - Null),以及计算包含 Null 值的表达式的值的一般规则生效,并且有关此处 Null 值对应于同一变量的信息丢失。 我们可以得出结论,在计算除逻辑运算以外的任何运算时,Null 值都被解释为 不适用,因此结果也是 Null 值。 在比较操作中使用 Null 值会导致意想不到的结果。 例如,以下表达式也会产生 Null 值,而不是预期的 Boolean True 或 False 值: (空<空); (无效的 ≤ 无效的); (空=空); (空≠空); (空>空); (空≥空)≔空; 因此,我们得出结论,不可能说 Null 值等于或不等于自身。 每次新出现的 Null 值都被视为独立的,并且每次 Null 值都被视为不同的未知值。 在这点上,Null 值与所有其他数据类型有着根本的不同,因为我们知道,对于之前传递的所有值以及它们的类型,它们彼此相等或不相等是安全的。 所以我们看到Null值并不是通常意义上的变量的值。 因此,无法比较包含 Null 值的变量或表达式的值,因为结果我们将收到的不是布尔 True 或 False 值,而是 Null 值,如下例所示: (x <空); (X ≤ 无效的); (x=空); (x≠空); (x > 空); (x ≥ Null) ≔ Null; 因此,与空值类比,要检查 Null 值的表达式,您必须使用特殊谓词: IsNull(<表达式>),字面意思是“为空”。 如果表达式包含 Null 或为 Null,则布尔函数返回 True,否则返回 False,但从不返回 Null。 IsNull 谓词可以应用于任何类型的变量和表达式。 当应用于空类型的表达式时,谓词将始终返回 False。 例如: 因此,确实,我们看到在第一种情况下,当 IsNull 谓词从零开始时,输出结果为 False。 在所有情况下,包括第二种和第三种情况,当逻辑函数的参数结果等于 Null 值时,以及在第四种情况下,当参数本身最初等于 Null 值时,谓词返回 True。 4.空值与逻辑运算 通常,数据库管理系统只直接支持三种逻辑运算:否定 ¬、合取 & 和析取 ∨。 继承 ⇒ 和等价 ⇔ 的操作用替换来表示: (x ⇒ y) ≔ (Øx ∨ y); (x ⇔ y) ≔ (x ⇒ y) & (y ⇒ x); 请注意,使用 Null 值时,这些替换完全保留。 有趣的是,使用否定运算符“¬”,任何操作合取 & 或析取 ∨ 都可以如下表示: (x & y) ≔¬ (¬x ∨¬y); (x ∨ y) ≔ ¬(¬x & ¬y); 这些替换以及之前的替换不受 Null 值的影响。 现在我们将给出否定、合取和析取的逻辑运算的真值表,但是除了通常的 True 和 False 值之外,我们还使用 Null 值作为操作数。 为方便起见,我们引入以下符号:代替 True,我们将写 t,而不是 False - f,而不是 Null - n。 1. 拒绝 二十。 值得注意的是关于使用 Null 值的否定操作的以下有趣点: 1) ¬¬x ≔ x - 双重否定定律; 2) ¬Null ≔ Null - Null 值是一个固定点。 2. 合取 x & y. 这个操作也有它自己的属性: 1) x & y ≔ y & x - 可交换性; 2) x & x ≔ x - 幂等性; 3) False & y ≔ False,这里的 False 是一个吸收元素; 4) True & y ≔ y,这里 True 是中性元素。 3. 析取 x ∨ y. 产品特点: 1) x ∨ y ≔ y ∨ x - 交换律; 2) x ∨ x ≔ x - 幂等性; 3) False ∨ y ≔ y,这里的False是中性元素; 4) True ∨ y ≔ True,这里 True 是一个吸收元素。 一般规则的一个例外是在作用条件下计算逻辑运算合取 & 和析取 ∨ 的规则 吸收定律: (假 & y) ≔ (x & 假) ≔ 假; (真 ∨ y) ≔ (x ∨ 真) ≔ 真; 制定这些附加规则,以便在将 Null 值替换为 False 或 True 时,结果仍将不依赖于该值。 正如前面针对其他类型的运算所展示的,在布尔运算中使用 Null 值也可能导致意外值。 例如,乍一看的逻辑被打破了 第三者排除法 (x ∨ ¬x) 和 反身定律 (x = x),因为对于 x ≔ Null,我们有: (x ∨ ¬x), (x = x) ≔ Null。 法律没有执行! 这与之前的解释方式相同:当将 Null 值代入表达式时,该值由同一变量报告的信息丢失,使用 Null 值的一般规则生效。 因此,我们得出结论:当以 Null 值作为操作数执行逻辑运算时,这些值由数据库管理系统确定为 适用但未知. 5.空值和条件检查 所以,从上面我们可以得出结论,在数据库管理系统的逻辑中,没有两个逻辑值(True 和 False),而是三个,因为 Null 值也被认为是可能的逻辑值之一。 这就是为什么它通常被称为未知值,Unknown value。 然而,尽管如此,在数据库管理系统中只实现了二值逻辑。 因此,具有 Null 值的条件(未定义的条件)必须由机器解释为 True 或 False。 默认情况下,DBMS 语言将具有 Null 值的条件识别为 False。 我们通过以下在数据库管理系统中实现条件 If 和 While 语句的示例来说明这一点: 如果 P 则 A 否则 B; 该条目的意思是:如果 P 评估为 True,则执行操作 A,如果 P 评估为 False 或 Null,则执行操作 B。 现在我们对这个运算符应用否定操作,我们得到: 如果 ¬P 则 B 否则 A; 反过来,该运算符的含义如下:如果 ¬P 的计算结果为 True,则执行操作 B,如果 ¬P 的计算结果为 False 或 Null,则将执行操作 A。 同样,正如我们所见,当出现 Null 值时,我们会遇到意想不到的结果。 关键是这个例子中的两个 If 语句是不等价的! 虽然其中一个是通过否定条件和重新排列分支,即通过标准操作从另一个获得的。 这样的操作符一般是等价的! 但在我们的示例中,我们看到条件 P 的空值在第一种情况下对应于命令 B,而在第二种情况下 - 对应于 A。 现在考虑 while 条件语句的动作: 而P做A; 乙; 这个运算符是如何工作的? 只要 P 为 True,就会执行动作 A,一旦 P 为 False 或 Null,就会执行动作 B。 但 Null 值并不总是被解释为 False。 例如,在完整性约束中,未定义的条件被识别为 True(完整性约束是施加在输入数据上并确保其正确性的条件)。 这是因为在这样的约束下,只有故意的虚假数据应该被拒绝。 同样,在数据库管理系统中,有一个特殊的 替换函数 IfNull(完整性约束,True), 可以显式表示 Null 值和未定义条件。 让我们使用这个函数重写条件 If 和 While 语句: 1) 如果 IfNull ( P, False) 然后 A 否则 B; 2) 而 IfNull( P, False) 做 A; 乙; 因此,如果替换函数 IfNull(expression 1, expression 2) 不包含 Null 值,则返回第一个表达式的值,否则返回第二个表达式的值。 需要注意的是,IfNull 函数返回的表达式的类型没有任何限制。 因此,使用此函数,您可以显式覆盖使用 Null 值的任何规则。 讲座 #3. 关系数据对象 1.关系表形式的要求 1. 关系表示的表格形式的第一个要求是有限性。 使用无限的表、关系或任何其他表示和数据组织是不方便的,很少证明付出的努力是合理的,而且,这个方向几乎没有实际应用。 但除此之外,相当预期,还有其他要求。 2. 表示关系的表的标题必须由一行组成 - 列的标题,并且具有唯一的名称。 不允许使用多级标题。 例如,这些: 通过选择合适的标题,将所有多层标题替换为单层标题。 在我们的示例中,指定转换后的表将如下所示: 我们看到每列的名称都是唯一的,因此可以随意交换它们,即它们的顺序变得无关紧要。 这非常重要,因为它是第三个属性。 3. 行的顺序不应该很重要。 然而,这个要求也不是严格限制的,因为任何表格都可以很容易地简化为所需的形式。 例如,您可以输入一个附加列来确定行的顺序。 在这种情况下,线条的排列不会发生任何变化。 以下是此类表的示例: 4. 表示关系的表中不应有重复的行。 如果表中有重复的行,可以通过引入负责每行重复数的附加列来轻松解决此问题,例如: 下面的属性也是非常值得期待的,因为它是编程和设计关系数据库的所有原则的基础。 5.所有列中的数据必须是同一类型。 此外,它们必须是简单类型。 让我们解释一下简单和复杂的数据类型。 简单数据类型是其数据值是非复合的,即它们不包含成分。 因此,列表、数组、树或类似的复合对象都不应该出现在表的列中。 这样的对象是 复合数据类型 - 在关系数据库管理系统中,它们本身以独立表关系的形式呈现。 2. 领域和属性 域和属性是创建和管理数据库理论中的基本概念。 让我们解释一下它是什么。 正式地, 属性域 (表示 主场(一)),其中a为属性,定义为对应属性a的同类型有效值的集合。 这种类型必须简单,即: dom(a) ⊆ {x | 类型(x)=类型(a)}; 属性 (表示为 a)又被定义为由属性名称 name(a) 和属性域 dom(a) 组成的有序对,即: a = (名称(a): dom(a)); 此定义使用“:”而不是通常的“,”(如标准有序对定义中一样)。 这样做是为了强调属性域和属性数据类型的关联。 以下是不同属性的一些示例: а1 =(课程:{1、2、3、4、5}); а2 = (MassaKg: {x | type(x) = real, x 0}); а3 = (LengthSm: {x | type(x) = real, x 0}); 注意属性 a2 和一个3 域正式匹配。 但是这些属性的语义是不同的,因为比较质量和长度的值是没有意义的。 因此,属性域不仅与有效值的类型相关联,还与语义含义相关联。 在关系的表格形式中,属性在表中显示为列标题,属性的域没有指定,而是隐含的。 它看起来像这样: 很容易看出,这里的每个标题都是1,以2,以3 表示关系的表的列是一个单独的属性。 3. 关系计划。 命名值元组 在 DBMS 的理论和实践中,关系模式和属性上元组的命名值的概念是基本的。 让我们把它们带来。 关系图式 (表示 S) 被定义为具有唯一名称的有限属性集,即: S = {一个 | a∈S}; 在表示关系的每个表中,所有列标题(所有属性)都组合到关系的架构中。 关系模式中的属性数量决定 度 它 关系 并表示为集合的基数:|S|. 关系模式可以与关系模式名称相关联。 如您所见,在关系表示的表格形式中,关系模式只不过是一行列标题。 S = {一个1,以2,以3,以4} - 此表的关系模式。 关系名称显示为表格的示意性标题。 在文本形式中,关系模式可以表示为属性名称的命名列表,例如: 学生(课本编号、姓氏、名字、父名、出生日期)。 在这里,与表格形式一样,属性域没有被指定而是隐含的。 根据定义,关系的模式也可以为空(S = ∅)。 诚然,这仅在理论上是可能的,因为实际上数据库管理系统永远不会允许创建空的关系模式。 属性上的命名元组值 (表示 吨(一)) 通过类比将属性定义为由属性名称和属性值组成的有序对,即: t(a) = (名字(a) : x), x ∈ dom(a); 我们看到属性值取自属性域。 在关系的表格形式中,属性上元组的每个命名值都是对应的表格单元格: 这里 t(a1), t(一2), t(一3) - 属性 a 上元组 t 的命名值1和2和3. 属性上命名元组值的最简单示例: (课程:5),(分数:5); 这里Course 和Score 分别是两个属性的名称,5 是它们取自其域的值之一。 当然,虽然这些值在两种情况下都是相等的,但它们在语义上是不同的,因为这两种情况下这些值的集合是互不相同的。 4. 元组。 元组类型 数据库管理系统中元组的概念可以从上一点直观地找到,当时我们谈到了元组在各种属性上的命名值。 所以, 元组 (表示 t, 来自英语。 tuple - "tuple") 与关系方案 S 被定义为这个元组在这个关系方案 S 中包含的所有属性上的命名值的集合。换句话说,属性取自 元组的范围,def(t), IE。: t ≡ t(S) = {t(a) | a ∈ def(t) ⊆ S;。 重要的是,不超过一个属性值必须对应于一个属性名称。 在关系的表格形式中,元组将是表的任何行,即: 这里吨1(S) = {t(a1), t(一2), t(一3), t(一4)} 和T2(S) = {t(a5), t(一6), t(一7), t(一8)} - 元组。 DBMS 中的元组在 类型 取决于其定义域。 元组被称为: 1) 部分的,如果它们的定义域包含在关系模式中或与关系模式一致,即 def(t) ⊆ S。 这是数据库实践中的常见情况; 2) 完全的,如果它们的定义域完全一致,则等于关系格式,即 def(t) = S; 3) 不完整,如果定义域完全包含在关系方案中,即 def(t) ⊂ S; 4) 无处定义,如果它们的定义域等于空集,即 def(t) = ∅。 让我们用一个例子来解释。 假设我们有下表给出的关系。 让这里 t1 = {10, 20, 30}, t2 = {10, 20, 空}, t3 = {空,空,空}。 那么很容易看出元组 t1 - 完整,因为它的定义域是 def(t1) = {a, b, c} = S。 元组 t2 - 不完整的,定义(t2) = { a, b} ⊂ S. 最后,元组 t3 - 没有在任何地方定义,因为它的 def(t3) = ∅。 应该注意,未在任何地方定义的元组是一个空集,但与关系方案相关联。 有时表示无处定义的元组:∅(S)。 正如我们在上面的示例中已经看到的,这样的元组是一个仅包含 Null 值的表行。 有趣的是,在 可比,即可能相等,只是具有相同关系模式的元组。 因此,例如,具有不同关系方案的两个无处定义的元组将不相等,正如预期的那样。 他们会有所不同,就像他们的关系模式一样。 5. 关系。 关系类型 最后,让我们将关系定义为金字塔的顶部,由所有先前的概念组成。 所以, 态度 (表示 r, 来自英语。 与关系模式 S 的关系)被定义为具有相同关系模式 S 的一组必然有限的元组。因此: r ≡ r(S) = {t(S) | t∈r}; 类比关系方案,关系中的元组数称为 关系力量 并表示为集合的基数:|r|. 关系,如元组,在类型上有所不同。 所以这种关系称为: 1) 部分的,如果关系中包含的任何元组都满足以下条件:[def(t) ⊆ S]。 这是(与元组一样)一般情况; 2) 完全的, 如果 ∀t ∈ r(S) 我们有 [def(t) = S]; 3) 不完整, 如果 ∃t ∈ r(S) def(t) ⊂ S; 4) 无处定义, 如果 ∀t ∈ r(S) [def(t) = ∅]。 让我们特别注意无处定义的关系。 与元组不同,处理此类关系涉及一些微妙之处。 关键是无处定义的关系可以有两种类型:它们可以是空的,或者它们可以包含单个无处定义的元组(这种关系用 {∅(S)} 表示)。 可比 (通过与元组类比),即可能相等,只是具有相同关系模式的关系。 因此,不同关系模式的关系是不同的。 在表格形式中,关系是表格的主体,行 - 列的标题,即字面意思 - 整个表格以及包含标题的第一行与之对应。 第 4 讲。关系代数。 一元运算 关系代数正如您可能猜到的那样,它是一种特殊类型的代数,其中所有操作都在关系数据模型(即关系)上执行。 在表格术语中,关系包括行、列和行 - 列的标题。 因此,自然一元操作是选择某些行或列以及更改列标题的操作 - 重命名属性。 1. 一元选择操作 我们将看到的第一个一元运算是 获取操作 - 根据某种原则从表示关系的表中选择行的操作,即选择满足某个或多个条件的行元组。 获取运算符 用 σ 表示, 采样条件 - P ,即运算符 σ 总是在元组 P 上具有特定条件,并且条件 P 本身是根据关系 S 的方案编写的。考虑到所有这些, 获取操作 在关系 S 相对于关系 r 的方案上将如下所示: σ r(S) ≡ σ r = {t(S) |t ∈ r & P t} = {t(S) |t ∈ r & IfNull(P t, False}; 该操作的结果将是具有相同关系模式 S 的新关系,由满足选择条件 P t 的原始关系操作数的元组 t(S) 组成。 很明显,为了对元组应用某种条件,需要替换元组属性的值而不是属性名称。 为了更好地理解这个操作是如何工作的,让我们看一个例子。 给出以下关系方案: S:课程(成绩册编号、姓氏、学科、年级)。 让我们采取以下选择条件: P =(主题=“计算机科学”和评估> 3)。 我们需要从初始关系操作数中提取那些包含通过“计算机科学”科目至少三分的学生的信息的元组。 让我们也从这个关系中得到以下元组: t0(S) ∈ r(S): {(Gradebook #: 100), (Surname: 'Ivanov'), (Subject: 'Databases'), (Score: 5)}; 将我们的选择条件应用于元组 t0,我们得到: 吨0 = ('数据库' = '计算机科学' and 5 > 3); 在这个特定的元组上,不满足选择条件。 一般来说,这个特定样本的结果 σ<Subject = '计算机科学' and Grade > 3 > Session 将有一个“会话”表,其中留下满足选择条件的行。 2. 一元投影操作 我们将研究的另一个标准一元运算是投影运算。 投影操作 是根据某些属性从表示关系的表中选择列的操作。 即,机器选择在投影中指定的原始操作数关系的那些属性(即,字面上的那些列)。 投影算子 用 [S'] 或 π 表示. 这里 S' 是关系 S 的原始模式的子模式,即它的一些列。 这是什么意思? 这意味着 S' 的属性比 S 少,因为只有那些满足投影条件的属性保留在 S' 中。 在表示关系 r(S' ) 的表中,行数与表 r(S) 中的行数一样多,而列数较少,因为只剩下与剩余属性对应的列。 因此,应用于关系 r(S) 的投影算子 π< S'> 会产生一个具有不同关系方案 r(S' ) 的新关系,由原始元组的投影 t(S) [S' ] 组成关系。 这些元组投影是如何定义的? 投影 原始关系 r(S) 的任何元组 t(S) 与子电路 S' 的关系由以下公式确定: t(S) [S'] = {t(a)|a ∈ def(t) ∩ S'}, S' ⊆S。 重要的是要注意重复的元组会从结果中排除,即表中不会有代表新元组的重复行。 考虑到以上所有因素,数据库管理系统方面的投影操作将如下所示: π r(S) ≡ π r ≡ r(S) [S'] ≡ r [S' ] = {t(S) [S'] | t∈r}; 让我们看一个说明 fetch 操作如何工作的示例。 让给定关系“Session”和这个关系的方案: S:课程(课本编号、姓氏、学科、年级); 我们将只对这个方案中的两个属性感兴趣,即学生的“Gradebook #”和“Last Name”,因此 S' 子模式将如下所示: S':(记录簿编号,姓氏)。 有必要将初始关系 r(S) 投影到子电路 S' 上。 接下来,让我们得到一个元组 t0(S) 从原始关系: t0(S) ∈ r(S): {(Gradebook #: 100), (Surname: 'Ivanov'), (Subject: 'Databases'), (Score: 5)}; 因此,该元组在给定子电路 S' 上的投影将如下所示: t0(S)S':{(账簿号码:100),(姓氏:'Ivanov')}; 如果我们从表的角度来讨论投影操作,那么原始关系的投影Session [gradebook number, Last name]就是Session表,从该表中删除了所有列,除了两个:gradebook number和Last name。 此外,所有重复的行也已被删除。 3.一元重命名操作 我们要看的最后一个一元运算是 属性重命名操作. 如果我们将关系称为表,则需要进行重命名操作以更改所有或部分列的名称。 重命名运算符 看起来像这样:ρ<φ>,这里是 φ - 重命名函数. 该函数在模式属性名称 S 和 Ŝ 之间建立一一对应关系,其中 S 分别是原始关系的模式,而 Ŝ 是具有重命名属性的关系的模式。 因此,应用于关系 r(S) 的运算符 ρ<φ> 给出了一个具有模式 Ŝ 的新关系,它由仅具有重命名属性的原始关系的元组组成。 让我们从数据库管理系统的角度来写重命名属性的操作: ρ<φ> r(S) ≡ ρ<φ>r = {ρ<φ> t(S)| t∈r}; 以下是使用此操作的示例: 让我们考虑一下我们已经熟悉的关系 Session 与方案: S:课程(课本编号、姓氏、学科、年级); 让我们引入一个新的关系模式 Ŝ,我们希望看到不同的属性名称,而不是现有的: Ŝ : (No. ZK, Surname, Subject, Score); 例如,数据库客户希望在您的开箱即用关系中查看其他名称。 要实现这个命令,需要设计如下的重命名函数: φ:(记录簿编号,姓氏,学科,年级)→(编号ZK,姓氏,学科,分数); 事实上,只有两个属性需要重命名,所以写下面的重命名函数而不是当前的是合法的: φ:(记录簿编号,等级) → (编号 ZK,分数); 此外,让已经熟悉的属于 Session 关系的元组也被给出: t0(S) ∈ r(S): {(Gradebook #: 100), (Surname: 'Ivanov'), (Subject: 'Databases'), (Score: 5)}; 将重命名运算符应用于此元组: ρ<φ>t0(S): {(ZK #: 100), (Surname: 'Ivanov'), (Subject: 'Databases'), (Score: 5)}; 因此,这是我们关系的元组之一,其属性已被重命名。 在表格中,比率 ρ < 成绩册编号,年级 → “No. ZK,分数 > 会话 - 这是通过重命名指定属性从“会话”关系表中获得的新表。 4. 一元运算的性质 一元运算与其他运算一样,具有某些属性。 让我们考虑其中最重要的一个。 一元选择、投影和重命名操作的第一个属性是表征关系基数比率的属性。 (回想一下,基数是一种或另一种关系中元组的数量。)很明显,这里我们分别考虑初始关系和应用一种或另一种操作的结果获得的关系。 请注意,一元运算的所有属性都直接来自它们的定义,因此它们可以很容易地解释,甚至可以根据需要独立推导。 所以: 1) 功率比: a) 对于选择操作: | σ r |≤ |r|; b) 对于投影操作:| r[S'] | ≤ |r|; c) 对于重命名操作:| ρ<φ>r | = |r|; 总的来说,我们看到对于两个算子,即选择算子和投影算子,原始关系操作数的幂大于通过应用相应操作从原始关系获得的关系的幂。 这是因为这两个select和project操作伴随的选择排除了一些不满足选择条件的行或列。 在所有行或列都满足条件的情况下,幂(即元组的数量)没有减少,因此公式中的不等式并不严格。 在重命名操作的情况下,关系的权力不会改变,因为在更改名称时,不会从关系中排除元组; 2) 幂等性质: a) 对于采样操作:σ σ r = σ ; b) 对于投影运算:r [S'] [S'] = r [S']; c) 对于重命名操作,一般情况下,幂等性是不适用的。 此属性意味着对任何关系连续两次应用相同的运算符相当于应用一次。 对于重命名关系属性的操作,一般来说可以应用这个属性,但是有特殊的保留和条件。 幂等性的性质经常被用来简化表达式的形式,并将其转化为更经济、更实际的形式。 我们要考虑的最后一个属性是单调性。 有趣的是,在任何情况下,所有三个运算符都是单调的。 3) 单调性: a) 对于获取操作:r1 ⊆ r2 ⇒σ r1 ⇒ σ r2; b) 对于投影操作:r1 ⊆ r2 ⇒ r1[S'] ⊆ r2 [S']; c) 对于重命名操作:r1 ⊆ r2 ⇒ ρ<φ>r1 ⊆ ρ<φ>r2; 关系代数中的单调性概念类似于普通的一般代数中的相同概念。 让我们澄清一下:如果最初的关系 r1 和2 以 r ⊆ r 的方式相互关联2,那么即使在应用了三个选择、投影或重命名运算符中的任何一个之后,这种关系也将被保留。 第5讲。关系代数。 二元运算 1.并、交、差的运算 任何操作都有自己的适用性规则,必须遵守这些规则,这样表达式和动作才不会失去意义。 并、交和差的二元集合论运算只能应用于必然具有相同关系模式的两个关系。 这种二元运算的结果将是由满足运算条件的元组组成的关系,但与操作数具有相同的关系方案。 1。 结果 联合行动 两个关系 r1(S) 和 r2(S) 会有一个新的关系 r3(S) 由关系 r 的元组组成1(S) 和 r2(S) 属于至少一个原始关系并且具有相同的关系模式。 所以这两个关系的交集是: r3(S) = r1(S) r2(S) = {t(S) | t∈r1 ∪t∈r2}; 为清楚起见,这里是一个表格示例: 给定两个关系: r1(小): r2(小): 我们看到第一个和第二个关系的方案是相同的,只是它们的元组数量不同。 这两个关系的联合将是关系 r3(S),对应下表: r3(S) = r1(S) r2(小): 所以,关系 S 的模式没有改变,只是元组的数量增加了。 2. 让我们继续考虑下一个二元运算—— 交叉口操作 两种关系。 正如我们从学校几何学中知道的那样,结果关系将仅包括原始关系中同时存在于两个关系 r 中的那些元组1(S) 和 r2(S)(再次注意相同的关系模式)。 两个关系的交集的操作将如下所示: r4(S) = r1(S)∩r2(S) = {t(S) | t∈r1 & t ∈ r2}; 再次考虑此操作对以表格形式呈现的关系的影响: r1(小): r2(小): 根据关系r的交集定义运算1(S) 和 r2(S) 会有一个新的关系 r4(S),其表视图如下所示: r4(S) = r1(S)∩r2(小): 事实上,如果我们查看第一个和第二个初始关系的元组,它们之间只有一个共同点:{b, 2}。 它成为新关系 r 的唯一元组4(S)。 3. 差分运算 两个关系的定义方式与前面的操作类似。 与前面的操作一样,操作数关系必须具有相同的关系方案,然后生成的关系将包括第一个关系中不在第二个关系中的所有元组,即: r5(S) = r1(S)\r2(S) = {t(S) | t∈r1 & t ∉ r2}; 已经众所周知的关系 r1(S) 和 r2(S),在表格视图中如下所示: r1(小): r2(小): 我们将在两个关系的交集的运算中考虑两个操作数。 然后,按照这个定义,得到的关系 r5(S) 将如下所示: r5(S) = r1(S)\r2(小): 所考虑的二进制操作是基本的;其他更复杂的操作是基于它们的。 2.笛卡尔积和自然连接操作 笛卡尔积运算和自然连接运算是积类型的二元运算,并且基于我们之前讨论的两个关系运算的并集。 尽管笛卡尔积运算的动作对许多人来说似乎很熟悉,但我们还是从自然积运算开始,因为它比第一个运算更普遍。 所以,考虑自然连接操作。 应该立即注意到,该操作的操作数可以是与不同方案的关系,这与联合、交集和重命名这三个二元操作相反。 如果我们考虑具有不同关系方案 r 的两个关系1(S1) 和 r2(S2),然后他们的 天然化合物 会有一个新的关系 r3(S3),它将仅包含在关系方案的交集处匹配的操作数元组。 因此,新关系的方案将大于原始关系的任何方案,因为它是它们的连接,“粘合”。 顺便说一句,在两个操作数关系中相同的元组,根据这种“粘合”发生,被称为 可连接. 让我们用数据库管理系统的公式语言来写自然连接操作的定义: r3(S3) = r1(S1)xr2(S2) = {t(小号1 ∪S2) | t[小号1] ε r1 &t(S2) ε r2}; 让我们考虑一个很好地说明自然连接的工作的例子,它的“粘合”。 让两个关系 r1(S1) 和 r2(S2),以表格形式表示,分别等于: r1(S1): r2(S2): 我们看到这些关系具有在方案 S 的交点处重合的元组1 和S2 关系。 让我们列出它们: 1) 关系 r 的元组 {a, 1}1(S1) 匹配关系 r 的元组 {1, x}2(S2); 2) 来自 r 的元组 {b, 1}1(S1) 也匹配来自 r 的元组 {1, x}2(S2); 3) 元组 {c, 3} 匹配元组 {3, z}。 因此,在自然连接下,新关系 r3(S3) 是通过精确地“粘合”在这些元组上获得的。 所以3(S3) 在表格视图中将如下所示: r3(S3) = r1(S1)xr2(S2): 事实证明,根据定义:方案 S3 不符合方案 S1, 也没有方案 S2,我们通过相交元组来“粘合”两个原始模式以获得它们的自然连接。 让我们示意性地展示在应用自然连接操作时如何连接元组。 让关系 r1 有一个条件形式: 和比率 r2 - 看法: 那么他们的自然联系将如下所示: 考虑到这个例子,我们看到关系操作数的“粘合”是根据我们之前给出的相同方案发生的。 手术 笛卡尔连接 是自然连接操作的一个特例。 更具体地说,在考虑笛卡尔积的运算对关系的影响时,我们特意规定在这种情况下我们只能谈论非相交的关系方案。 作为应用这两种操作的结果,得到的关系等于操作数关系模式的并集,只有它们的元组的所有可能对落入两个关系的笛卡尔积,因为操作数的模式在任何情况下都不应该相交。 因此,基于上述,我们编写了笛卡尔积运算的数学公式: r4(S4) = r1(S1)xr2(S2) = {t(小号1 ∪小号2) | t[S1] ε r1 &t(S2) ε r2}, 小号1 ∩S2= ∅; 现在让我们看一个示例,以展示应用笛卡尔积运算时生成的关系模式的外观。 让两个关系 r1(S1) 和 r2(S2),以表格形式呈现如下: r1(S1): r2(S2): 所以我们看到没有一个关系元组 r1(S1) 和 r2(S2),事实上,它们的交点并不重合。 因此,在得到的关系 r4(S4) 第一个和第二个操作数关系的所有可能的元组对都将下降。 得到: r4(S4) = r1(S1)xr2(S2): 我们得到了一个新的关系方案r4(S4) 不是像前一种情况那样通过“粘合”元组,而是通过枚举在原始方案的交集中不匹配的所有可能的不同元组对。 同样,与自然连接的情况一样,我们给出笛卡尔积运算的示意性示例。 让 r1 设置如下: 和比率 r2 给定: 那么他们的笛卡尔积可以示意性地表示如下: 正是通过这种方式,在应用笛卡尔积运算时得到了结果关系。 3. 二元运算的性质 从上面对并、交、差、笛卡尔积和自然连接的二元运算的定义,性质如下。 1. 与一元运算的情况一样,第一个性质说明了 功率比 关系: 1)对于联合操作: |r1 ∪r2| ≤ |r1| + |r2|; 2)对于相交操作: |r1 ∩r2 | ≤ 最小值(|r1|, |r2|); 3)对于差分操作: |r1 \r2| ≤|r1|; 4)对于笛卡尔积运算: |r1 xr2| = |r1| |r2|; 5)对于自然连接操作: |r1 xr2| ≤|r1| |r2|. 正如我们所记得的,幂比表征了关系中元组的数量在应用一个或另一个操作后如何变化。 那么我们看到了什么? 力量 协会 两个关系 r1 和2 小于原始关系操作数的基数之和。 为什么会这样? 问题是当你合并时,匹配的元组消失,相互重叠。 因此,参考我们在完成此操作后考虑的示例,您可以看到在第一个关系中有两个元组,在第二个 - 三个,在结果 - 四个,即小于五个(总和关系操作数的基数)。 通过匹配元组 {b, 2},这些关系“粘合在一起”。 结果力量 十字路口 两个关系小于或等于原始操作数关系的最小基数。 让我们转向这个操作的定义:只有在两个初始关系中都存在的元组才能进入结果关系。 这意味着新关系的基数不能超过元组数是两者中最小的关系操作数的基数。 结果的幂可以等于这个最小基数,因为当具有较低基数的关系的所有元组与第二个关系操作数的一些元组重合时,总是允许这种情况。 操作时 差异 一切都是微不足道的。 事实上,如果第二个关系中也存在的所有元组都从第一个关系操作数中“减去”,那么它们的数量(以及它们的幂)将会减少。 如果第一个关系的任何一个元组都没有匹配第二个关系的任何元组,即没有什么可以“减去”,它的力量不会减少。 有趣的是,如果操作 笛卡尔积 结果关系的幂恰好等于两个操作数关系的幂的乘积。 很明显,这是因为原始关系的所有可能的元组对都写入了结果中,并且没有排除任何内容。 最后,操作 自然联系 得到一个关系,其基数大于或等于两个原始关系的基数的乘积。 再次发生这种情况是因为操作数关系通过匹配元组“粘合”,而不匹配的元组完全从结果中排除。 2. 幂等性: 1) 对于联合运算:r ∪ r = r; 2) 对于交集运算:r ∩ r = r; 3)对于差分运算:r\r≠r; 4)对于笛卡尔积运算(一般情况下,该属性不适用); 5) 对于自然连接操作:rxr = r。 有趣的是,幂等性并不适用于上述所有运算,对于笛卡尔积的运算,它根本不适用。 事实上,如果你将任何关系与自身结合、相交或自然连接,它不会改变。 但是如果你从一个完全等于它的关系中减去,结果将是一个空关系。 3. 交换性质: 1)对于联合操作: r1 ∪r2 = r2 ∪r1; 2)对于相交操作: r∩r=r∩r; 3)对于差分操作: r1 \r2 ≠r2 \r1; 4)对于笛卡尔积运算: r1 xr2 = r2 xr1; 5)对于自然连接操作: r1 xr2 = r2 xr1. 交换性性质适用于除差分运算之外的所有运算。 这很容易理解,因为它们的组成(元组)不会因重新排列位置关系而改变。 并且在应用差分运算时,重要的是哪个操作数关系先出现,因为这取决于哪个关系的哪些元组将作为参考,即其他元组将与哪些元组进行比较以排除。 4. 关联属性: 1)对于联合操作: (r1 ∪r2)∪r3 = r1 ∪(r2 ∪r3); 2)对于相交操作: (r1 ∩r2)∩r3 = r1 ∩(r2 ∩r3); 3)对于差分操作: (r1 \r2)\r3 ≠r1 \(r2 \r3); 4)对于笛卡尔积运算: (r1 xr2)xr3 = r1 x(r2 xr3); 5)对于自然连接操作: (r1 xr2)xr3 = r1 x(r2 xr3). 我们再次看到除了差异操作之外的所有操作都执行了该属性。 这与应用交换性的情况相同。 总的来说,并、交、差和自然连接的操作并不关心操作数关系的顺序。 但是,当关系被彼此“夺走”时,秩序就会发挥主导作用。 基于上述性质和推理,可以得出以下结论:最后三个性质,即幂等性、交换性和结合性的性质,对于我们所考虑的所有运算都是正确的,除了两个关系的差运算,其中所指出的三个属性都没有得到满足,只有一种情况下该属性被认为不适用。 4.连接操作选项 以前面考虑的选择、投影、重命名和并、交、差、笛卡尔积和自然连接的二元运算为基础(所有这些通常都称为 连接操作),我们可以引入使用上述概念和定义派生的新操作。 此活动称为编译。 加入操作选项. 连接操作的第一个这样的变体是操作 内部连接 根据指定的连接条件。 某些特定条件的内连接操作被定义为笛卡尔积和选择操作的导数操作。 我们写出这个操作的公式定义: r1(S1) X P r2(S2) = σ (r1 xr2), 小号1 ∩S2 =∅; 这里 P = P<S1 ∪小号2> - 对原始关系操作数的两个方案的并集施加的条件。 正是通过这个条件,从关系 r 中选择元组1 和2 到结果关系中。 请注意,内连接操作可以应用于具有不同关系模式的关系。 这些方案可以是任何方案,但在任何情况下都不应相交。 作为内部连接操作结果的原始操作数关系的元组称为 可连接元组. 为了直观地说明内连接操作的操作,我们将给出下面的例子。 给定两个关系 r1(S1) 和 r2(S2) 具有不同的关系方案: r1(S1): r2(S2): 下表将给出在条件 P = (b1 = b2) 上应用内连接操作的结果。 r1(S1) X P r2(S2): 因此,我们看到表示关系的两个表的“粘合”确实发生在满足内部连接操作 P = (b1 = b2) 的条件的那些元组中。 现在,基于已经介绍的内连接操作,我们可以介绍操作 左外连接 и 右外连接. 让我们解释一下。 左外连接操作的结果是内连接的结果,用左源关系操作数的不可连接元组完成。 类似地,右外连接操作的结果被定义为内连接操作的结果,该内连接操作增加了右手源关系操作数的不可连接元组。 左右外连接操作的结果关系如何被补充的问题是相当值得期待的。 一个关系操作数的元组在另一个关系操作数的模式上补充 空值. 值得注意的是,这种方式引入的左右外连接操作是内连接操作的派生操作。 为了写出左右外连接操作的一般公式,我们将进行一些额外的构造。 给定两个关系 r1(S1) 和 r2(S2) 具有不同的关系方案 S1 和S2,它们不相交。 由于我们已经规定了左右内连接操作是导数,所以我们可以得到以下确定左外连接操作的辅助公式: 1)3 (S2 ∪小号1) ≔ r1(S1) X Pr2(S2); r 3 (S2 ∪小号1) 只是关系 r 的内连接的结果1(S1) 和 r2(S2)。 左外连接是内连接的派生操作,这就是我们用它开始构造的原因; 2)4(S1) ≔ r 3(S2 ∪S1) [小号1]; 因此,借助一元投影操作,我们选择了左侧初始关系操作数 r 的所有可连接元组1(S1)。 结果指定为 r4(S1) 为方便使用; 3)5 (S1) ≔ r1(S1)\r4(S1); 这里 r1(S1) 都是左源关系操作数的元组,并且 r4(S1) - 它自己的元组,仅连接。 因此,使用差分的二元运算,关于 r5(S1) 我们得到了左操作数关系的所有不可连接元组; 4)6(S2)≔{∅(S2)}; {∅(小号2)} 是与模式 (S2) 只包含一个元组,由 Null 值组成。 为方便起见,我们将此比率表示为 r6(S2); 5)7 (S2 ∪小号1) ≔ r5(S1)xr6(S2); 这里我们取了左操作数关系的未连接元组(r5(S1)) 并在第二个关系操作数 S 的方案上对其进行了补充2 空值,即笛卡尔将由这些相同的不可连接元组组成的关系乘以关系 r6(S2)第XNUMX段所界定; 6)1(S1)→x P r2(S2) ≔ (r1 x P r2)∪r7 (S2 ∪小号1); 这是 左外连接,可以看出,通过原始关系操作数 r 的笛卡尔积的并集获得1 和2 和关系 r7 (S2 ∪ S1)第XNUMX段所界定。 现在我们有了所有必要的计算,不仅可以确定左外连接的操作,而且可以通过类比来确定右外连接的操作。 所以: 1) 操作 左外连接 严格来说,它看起来像这样: r1(S1)→x P r2(S2) ≔ (r1 x P r2) ∪ [(r1 \(r1 x P r2) [小号1]) x {∅(S2)}]; 2) 操作 右外连接 定义与左外连接操作类似,形式如下: r1(S1)→x P r2(S2) ≔ (r1 x P r2) ∪ [(r2 \(r1 x P r2) [小号2]) x {∅(S1)}]; 这两个派生操作只有两个属性值得一提。 1. 交换性: 1)对于左外连接操作: r1(S1)→x P r2(S2) ≠ r2(S2)→x P r1(S1); 2)对于右外连接操作: r1(S1) ←x P r2(S2) ≠ r2(S2) ←x P r1(S1) 因此,我们看到这些操作在一般形式下不满足交换性,但同时左右外连接的操作互为逆,即以下情况为真: 1)对于左外连接操作: r1(S1)→x P r2(S2) = r2(S2)→x P r1(S1); 2)对于右外连接操作: r1(S1) ←x P r2(S2) = r2(S2) ←x Pr1(S1). 2.左右外连接操作的主要属性是它们允许 重建 根据特定连接操作的最终结果的初始关系操作数,即执行以下操作: 1)对于左外连接操作: r1(S1) = (r1 →x P r2) [小号1]; 2)对于右外连接操作: r2(S2) = (r1 ←x P r2) [小号2]. 因此,我们看到第一个原始关系操作数可以从左右连接操作的结果中恢复,更具体地说,通过应用到这个连接的结果(r1 xr2) 投影到方案 S 上的一元运算1, [小号1]. 类似地,第二个原始关系操作数可以通过应用右外连接(r1 xr2) 投影到关系 S 方案上的一元运算2. 下面举个例子,更详细的考虑左右外连接的操作。 让我们介绍一下已经熟悉的关系 r1(S1) 和 r2(S2) 具有不同的关系方案: r1(S1): r2(S2): 左关系操作数 r 的不可连接元组2(S2) 是一个元组 {d, 4}。 按照定义,它们应该补充两个原始操作数关系的内部连接的结果。 关系 r 的内连接条件1(S1) 和 r2(S2) 我们也保持不变:P = (b1 = b2)。 然后是运算结果 左外连接 会有下表: r1(S1)→x P r2(S2): 实际上,正如我们所看到的,由于左外连接操作的影响,内连接操作的结果被左的不可连接元组补充,即在我们的例子中,第一个关系-操作数。 根据定义,第二个(右)源关系操作数方案中元组的补充是在 Null 值的帮助下发生的。 和结果类似 右外连接 与之前一样,原始关系操作数 r 的条件 P = (b1 = b2)1(S1) 和 r2(S2) 如下表: r1(S1) ←x P r2(S2): 实际上,在这种情况下,内部连接操作的结果应该用右边的不可连接元组来补充,在我们的例子中,是第二个初始关系操作数。 这样的元组,不难看出,在第二个关系 r2(S2) 一,即{2, y}。 接下来,我们根据右外连接操作的定义,在第一个操作数的方案中用空值补充第一个(左)操作数的元组。 最后,我们看一下上面第三版的join操作。 全外连接操作. 该操作不仅可以看作是从内连接操作派生的操作,而且可以看作是左右外连接操作的并集。 全外连接操作 定义为用左右初始操作数关系的不可连接元组完成相同的内连接(如左和右外连接的定义)的结果。 基于这个定义,我们给出这个定义的公式形式: r1(S1) ↔x P r2(S2) = (r1 →x P r2)∪(r1 ←x P r2); 全外连接操作也具有与左右外连接操作类似的性质。 只是由于全外连接操作的原始互惠性质(毕竟它被定义为左右外连接操作的并集),它执行 交换性: r1(S1) ↔x P r2(S2)=r2(S2) ↔ x P r1(S1); 为了完成对连接操作选项的考虑,让我们看一个示例,说明完全外连接操作的操作。 我们引入两个关系 r1(S1) 和 r2(S2) 和连接条件。 让 r1(S1) r2(S2): 并设关系连接条件 r1(S1) 和 r2(S2) 将是:P = (b1 = b2),如前面的示例所示。 然后是关系 r 的全外连接操作的结果1(S1) 和 r2(S2) 由条件 P = (b1 = b2) 将有下表: r1(S1) ↔x P r2(S2): 因此,我们看到完全外连接操作清楚地证明了它的定义是左外连接操作和右外连接操作结果的并集。 内部连接操作的结果关系由同时不可连接的元组作为左边的补充(首先,r1(S1)) 和右(第二个,r2(S2)) 的原始关系操作数。 5. 衍生操作 因此,我们考虑了连接操作的各种变体,即内连接、左连接、右连接和完全外连接的操作,它们是关系代数的八种原始操作的派生:选择、投影、重命名和二元操作的一元操作。并、交、差、笛卡尔积和自然连接。 但即使在这些原始运算中,也有衍生运算的例子。 1.例如,操作 十字路口 两个比率是对相同两个比率的差异进行运算的导数。 让我们展示一下。 交集运算可以用以下公式表示: r1(S)∩r2(S) = r1 \r1 \r2 或者,给出相同的结果: r1(S)∩r2(S) = r2 \r2 \r1; 2.另一个从八个原始操作派生的基础操作的例子是操作 自然联系. 在其最一般的形式中,该运算源自笛卡尔积的二元运算以及选择、投影和重命名属性的一元运算。 然而,反过来,内连接操作是笛卡尔关系积的相同操作的衍生操作。 因此,为了证明自然连接运算是派生运算,请考虑以下示例。 让我们比较前面的自然连接和内连接操作示例。 给定两个关系 r1(S1) 和 r2(S2) 将充当操作数。 他们是平等的: r1(S1): r2(S2): 正如我们之前已经收到的,这些关系的自然连接操作的结果将是一个如下形式的表: r3(S3) ≔ r1(S1)xr2(S2): 以及相同关系 r 的内连接的结果1(S1) 和 r2(S2) 由条件 P = (b1 = b2) 将有下表: r4(S4) ≔ r1(S1) X P r2(S2): 让我们比较这两个结果,得到的新关系 r3(S3) 和 r4(S4). 很明显,自然连接操作是通过内连接操作来表达的,但最重要的是,它具有特殊形式的连接条件。 让我们写一个数学公式,将自然连接操作的动作描述为内连接操作的导数。 r1(S1)xr2(S2) = { ρ<φ1> r1 x E ρ< φ2>r2}[小号1 ∪小号2], 其中 E - 连通性条件 元组; E=∀a∈S1 ∩S2 [IsNull(b1) & IsNull(2) ∪b1 = b2]; b1 = φ1 (姓名(a)), b2 = φ2 (姓名(一)); 这是其中之一 重命名函数 ϕ1 是相同的,还有另一个重命名函数(即 φ2) 重命名我们的模式相交的属性。 元组的连通性条件 E 写成一般形式,考虑到空值的可能出现,因为内连接运算(如上所述)是两个关系的笛卡尔积运算的导数运算,并且一元选择操作。 6. 关系代数的表达式 让我们展示之前考虑过的关系代数的表达式和操作如何用于各种数据库的实际操作中。 例如,让我们可以使用一些商业数据库的片段: 供应商 (供应商代码, 供应商名称, 供应商城市); 工具 (工具代码,工具名称,...); 交货(供应商代码, 零件代号); 带下划线的属性名称[1] 是关键(即标识)属性,每个属性都有其自己的关系。 假设我们作为该数据库的开发者和有关该主题的信息的保管人,在这些供应商不提供任何工具的情况下,被要求获取供应商的名称(供应商名称)及其位置(供应商城市)通用名称“钳子”。 为了在我们可能非常大的数据库中确定满足此要求的所有供应商,我们编写了一些关系代数表达式。 1.我们形成“供应商”和“供应商”关系的自然连接,以便与每个供应商匹配他提供的零件的代码。 新的关系——应用自然连接运算的结果——为了方便进一步应用,我们用r表示1. 供应商 x 供应品 ≔ r1 (供应商代码、供应商名称、供应商城市、 在括号中,我们列出了这个自然连接操作所涉及的关系的所有属性。 我们可以看到“Vendor ID”属性是重复的,但是在交易摘要记录中,每个属性名称应该只出现一次,即: 供应商 x 供应品 ≔ r1 (供应商代码、供应商名称、供应商城市、仪器代码); 2. 再次我们形成一个自然的联系,只是这一次在第一段中获得的关系和关系文书。 我们这样做是为了将此工具的名称与上一段中获得的每个工具代码相匹配。 r1 x 工具 [工具代码、工具名称] ≔ r2 (供应商代码、供应商名称、供应商城市、 结果将用 r 表示2,重复属性被排除: r1 x 工具 [工具代码、工具名称] ≔ r2 (供应商代码、供应商名称、供应商城市、仪器代码、仪器名称); 请注意,我们仅从工具关系中获取两个属性:“工具代码”和“工具名称”。 为此,我们可以从关系 r 的符号中看出2,应用一元投影运算:Tools [Tool code, Tool name],即如果关系Tools以表格的形式呈现,则此投影运算的结果将是标题为“Tool code”的前两列和“工具名称”分别为“。 有趣的是,我们已经考虑过的前两个步骤非常通用,也就是说,它们可用于实现任何其他请求。 但接下来的两点又代表了实现我们面前的特定任务的具体步骤。 3.根据条件<"Tool name" = "Pliers">相对于比率r编写一元选择操作2在上一段中获得。 而我们反过来对这个操作的结果应用一元投影操作[Supplier Code, Supplier Name, Supplier City],以便得到这些属性的所有值,因为我们需要根据命令。 所以: (σ<工具名称 = "钳子"> r2) [供应商代码、供应商名称、供应商城市] ≔ r3 (供应商代码、供应商名称、供应商城市、工具代码、工具名称)。 在所得比率中,用 r 表示3,只有那些供应商(及其所有识别数据)提供通用名称为“钳子”的工具。 但是根据订单,我们需要挑出那些相反不提供此类工具的供应商。 因此,让我们继续我们算法的下一步,写下最后一个关系代数表达式,这将为我们提供我们正在寻找的信息。 4.首先,让我们来区分“供应商”的比率和r的比率3,并且在应用这个二元运算之后,我们对“供应商名称”和“供应商城市”属性应用一元投影运算。 (供应商\r3) [供应商名称,供应商城市] ≔ r4 (供应商代码、供应商名称、供应商城市); 结果指定为 r4,这种关系只包括原始“供应商”关系中与我们订单条件相对应的那些元组。 因此,我们已经展示了如何使用关系代数的表达式和运算,您可以对任意数据库执行各种操作、执行各种命令等。 第 6 讲 SQL 语言 让我们先介绍一点历史背景。 设计用于与数据库交互的 SQL 语言出现在 1970 年代中期。 (第一次出版可追溯到 1974 年),由 IBM 开发,作为实验性关系数据库管理系统项目的一部分。 该语言的原始名称是 SEQUEL(结构化 English 查询语言)——仅部分反映了这种语言的本质。 最初,在其发明之后和 SQL 语言的主要操作期间,它的名称是短语 Structured Query Language 的缩写,翻译为“结构化查询语言”。 当然,该语言主要侧重于对关系数据库的查询公式化,这对用户来说是方便且易于理解的。 但事实上,几乎从一开始,它就是一门完整的数据库语言,除了提供查询和操作数据库的方法外,还提供以下特性: 1) 定义和操作数据库模式的方法; 2) 定义完整性约束和触发器的方法(后面会提到); 3) 定义数据库视图的方法; 4) 定义支持有效执行请求的物理层结构的方法; 5) 授权访问关系及其领域的方法。 该语言缺乏从并行事务方面显式同步访问数据库对象的方法:从一开始就假定必要的同步是由数据库管理系统隐式执行的。 目前,SQL 不再是缩写,而是一种独立语言的名称。 此外,目前,结构化查询语言已在所有商业关系数据库管理系统和几乎所有最初不是基于关系方法的 DBMS 中实现。 所有的制造公司都声称他们的实现符合 SQL 标准,实际上结构化查询语言的实现方言非常接近。 这并没有立即实现。 大多数现代商业数据库管理系统的一个特点是难以比较现有的 SQL 方言,即缺乏对语言的统一描述。 通常,描述分散在各种手册中,并与与结构化查询语言不直接相关的系统特定语言特征的描述混合在一起。 尽管如此,可以说基本的 SQL 语句集,包括用于确定数据库模式、获取和操作数据、授权数据访问、支持在编程语言中嵌入 SQL 和动态 SQL 语句的语句,在商业实现和或多或少符合标准。 随着时间的推移和对结构化查询语言的研究,已经有可能实现数据检索语句、数据操作和修复数据库完整性约束的语法和语义的明确标准化的标准。 已经指定了用于定义关系的主键和外键以及所谓的完整性检查约束的方法,它们是立即检查的 SQL 完整性约束的子集。 定义外键的工具可以很容易地制定所谓的数据库引用完整性的要求(我们将在后面讨论)。 这个在关系型数据库中很常见的需求,也可以基于 SQL 完整性约束的一般机制来制定,但是基于外键概念的制定更加简单易懂。 因此,考虑到这一切,目前,结构化查询语言不仅仅是一种语言的名称,而是一整类语言的名称,因为尽管有现有的标准,但结构化查询语言的各种方言都被实现了在各种数据库管理系统中,当然,它们有一个共同的基础。 1.Select语句是结构化查询语言的基本语句 在 SQL 结构化查询语言中,Select 语句占据了中心位置,它实现了使用数据库时最需要的操作——查询。 Select 运算符计算关系代数表达式和伪关系代数表达式。 在本课程中,我们将只考虑我们已经介绍过的关系代数的一元和二元运算的实现,以及使用所谓的子查询的查询的实现。 顺便说一下,应该注意的是,在使用关系代数运算的情况下,重复的元组可能会出现在结果关系中。 结构化查询语言的规则中并没有严格禁止关系中存在重复行(与普通的关系代数不同),因此没有必要从结果中排除重复行。 那么让我们看一下Select语句的基本结构。 它非常简单,包括以下标准强制性短语: 选择... 从... 在哪里... ; 代替每一行中的省略号的应该是特定数据库的关系、属性和条件以及它的任务。 在最一般的情况下,基本的 Select 结构应该如下所示: 选择 选择一些属性 从 从这样的关系 其中 用这样那样的条件来采样元组 因此,我们从关系方案(某些列的标题)中选择属性,同时指出我们从哪些关系(显然可能有几个)中进行选择,最后,根据我们停止选择的条件某些元组。 重要的是要注意属性引用是使用它们的名称进行的。 因此,得到以下 工作算法 这个基本的 Select 语句: 1) 记住从关系中选择元组的条件; 2) 检查哪些元组满足指定的属性。 这样的元组会被记住; 3)输出Select语句基本结构第一行列出的属性及其值。 (如果我们说关系的表格形式,那么表格的那些列将被显示,其中的标题被列为必要的属性;当然,列不会完全显示,在每个列中只有那些元组满足指定条件的将保留。) 考虑这样一个例子。 让我们给出以下关系 r1,作为一些书店数据库的片段: 让我们也可以通过 Select 语句获得以下表达式: 选择 书名、作者 从 r1 其中 书价>200; 此运算符的结果将是以下元组片段: (手机,S. King)。 (在下文中,我们将考虑使用这种基本结构的许多查询实现示例,并详细研究其应用。) 2.结构化查询语言中的一元运算 在本节中,我们将考虑如何使用 Select 运算符在结构化查询语言中实现已经熟悉的选择、投影和重命名一元操作。 重要的是要注意,如果之前我们只能处理单个操作,那么在一般情况下,即使是单个 Select 语句也允许我们定义整个关系代数表达式,而不仅仅是单个操作。 那么,让我们直接分析结构化查询语言中一元运算的表示。 1. 取样操作. SQL中的选择操作是通过如下形式的Select语句实现的: 选择 所有属性 从 关系名称 其中 选择条件; 在这里,您可以使用“*”符号,而不是写“所有属性”。 在结构化查询语言理论中,此图标表示从关系模式中选择所有属性。 此处(以及在所有其他操作实现中)的选择条件被写成带有标准连接词 not (not)、and (and) 或 (or) 的逻辑表达式。 关系属性由它们的名称引用。 考虑一个例子。 让我们定义以下关系方案: 学业表现 (成绩簿编号、学期、学科代码, 评级, 日期); 在这里,如前所述,带下划线的属性形成关系键。 让我们编写如下形式的 Select 语句,实现一元选择操作: 选择* 从学习成绩 其中成绩簿 # = 100 和学期 = 6; 很明显,作为这个语句的结果,机器将显示一个学生第六学期的成绩为一百。 2. 投影操作. 结构化查询语言中的投影操作比提取操作更容易实现。 回想一下,在应用投影操作时,不是选择行(如应用选择操作时),而是选择列。 因此,列出所需列的标题(即属性名称)就足够了,而无需指定任何无关的条件。 总的来说,我们得到以下形式的运算符: 选择 属性名称列表 从 关系名称; 应用此语句后,机器将返回关系表中名称在此 Select 语句的第一行中指定的那些列。 正如我们前面提到的,没有必要从结果关系中排除重复的行和列。 但是,如果在订单或任务中需要消除重复项,则应使用结构化查询语言的特殊选项 - 不同. 此选项设置从关系中自动消除重复元组。 应用此选项后,Select 语句将如下所示: 选择 不同的属性名称列表 从 关系名称; 在 SQL 中,表达式的可选元素有一种特殊的表示法 - 方括号 [...]。 因此,在最一般的形式中,投影操作将如下所示: 选择 [distinct] 属性名称列表 从 关系名称; 但是,如果应用操作的结果保证不包含重复项,或者重复项仍然可以接受,则选项 不同 最好不要指定以免弄乱记录,即出于操作员性能的原因。 让我们考虑一个示例,说明在没有重复的情况下 XNUMX% 置信的可能性。 让我们已知的关系图式给出: 学业表现 (成绩簿编号、学期、学科代码,评级,日期)。 给出以下 Select 语句: 选择 成绩簿编号、学期、学科代码 从 学业表现; 在这里,很容易看出,运算符返回的三个属性构成了关系的键。 这就是为什么选择 不同 变得多余,因为保证没有重复。 这是根据称为唯一约束的键的要求得出的。 稍后我们将更详细地考虑此属性,但如果该属性是键,则其中没有重复项。 3. 重命名操作. 在结构化查询语言中重命名属性的操作非常简单。 即通过以下算法在现实中体现: 1)在Select短语的属性名列表中,列出了那些需要重命名的属性; 2) 特殊关键字 as 被添加到每个指定的属性中; 3) 每次出现 as 后,都标明了对应属性的名称,需要将原名称更改为该属性名称。 因此,考虑到以上所有,重命名属性操作对应的语句将如下所示: 选择 属性名称 1 作为新属性名称 1,... 从 关系名称; 让我们用一个例子来展示这个操作符是如何工作的。 给出我们已经熟悉的关系图: 学业表现 (成绩簿编号、学期、学科代码,评级,日期); 让我们有一个命令来改变一些属性的名称,即,而不是“账簿号码”应该是“账号”,而不是“分数”-“分数”。 让我们写下实现这个重命名操作的 Select 语句的样子: 选择 记录簿为记录号、学期、学科代码、成绩为分数、日期 从 学业表现; 因此,应用此运算符的结果将是一个新的关系模式,它与原始“成就”关系模式的不同之处在于两个属性的名称。 3.结构化查询语言中的二元运算 与一元运算一样,二元运算在结构化查询语言或 SQL 中也有自己的实现。 那么,让我们考虑一下我们已经通过的二元运算在这种语言中的实现,即联合、交集、差分、笛卡尔积、自然连接、内连接和左连接、右连接、全外连接的操作。 1. 联盟运作. 为了实现组合两个关系的操作,需要同时使用两个 Select 操作符,每个操作符对应一个原始的关系操作数。 并且需要对这两个基本的 Select 语句进行特殊操作 工会. 考虑到以上所有,让我们用结构化查询语言的语义写下联合操作的样子: 选择 列出关系 1 的属性名称 从 关系名称 1 工会 选择 列出关系 2 的属性名称 从 关系名称 2; 需要注意的是,被连接的两个关系的属性名称列表必须引用兼容类型的属性并以一致的顺序列出。 如果不满足此要求,则无法满足您的请求,并且计算机将显示错误消息。 但值得注意的是,这些关系中属性本身的名称可能不同。 在这种情况下,生成的关系被分配在第一个 Select 语句中指定的属性名称。 您还需要知道使用联合操作会自动从结果关系中排除所有重复的元组。 因此,如果您需要在最终结果中保留所有重复行,而不是 Union 操作,您应该使用此操作的修改 - 操作 联合所有. 在这种情况下,组合两个关系的操作将如下所示: 选择 列出关系 1 的属性名称 从 关系名称 1 联合所有 选择 列出关系 2 的属性名称 从 关系名称 2; 在这种情况下,不会从结果关系中删除重复的元组。 使用前面提到的 Select 语句中可选元素和选项的表示法,我们编写了结构化查询语言中连接两个关系的最一般形式的操作: 选择 列出关系 1 的属性名称 从 关系名称 1 联盟 [全部] 选择 列出关系 2 的属性名称 从 关系名称 2; 2. 路口操作. 结构化查询语言中的交集运算和两个关系的差运算以类似的方式实现(我们考虑最简单的表示方法,因为方法越简单,越经济,越相关,因此最需求)。 因此,我们将分析使用 键. 该方法涉及两个 Select 构造的参与,但它们并不相等(如联合操作的表示),其中一个可以说是“子构造”,“子循环”。 这样的算子通常被称为 子查询. 所以,假设我们有两个关系方案(R1 和R.2),大致定义如下: R1 (关键,...)和 R2 (钥匙,...); 在记录这个操作的时候,我们也会用到特殊的选项 in,它的字面意思是“在”或(在这种特殊情况下)“包含在”。 因此,考虑到以上所有情况,使用结构化查询语言对两个关系的交集的操作将编写如下: 选择 * 从 R1 其中 键入 (选择 关键 从 R2); 因此,我们看到这种情况下的子查询将是括号中的运算符。 在我们的例子中这个子查询返回一个关系 R 的键值列表2. 并且,根据我们的运算符符号,从选择条件的分析来看,只有关系 R 的那些元组才会落入结果关系1,其键包含在关系 R 的键列表中2. 也就是说,在最后的关系中,如果我们回忆一下两个关系的交集的定义,那么只会保留属于这两个关系的那些元组。 3. 差分运算. 如前所述,两个关系的差的一元运算的实现与交集的运算类似。 在这里,除了使用 Select 运算符的主查询之外,还使用了第二个辅助查询 - 所谓的子查询。 但是与前面操作的实现不同的是,在实现差分操作的时候,需要用到另外一个关键字,即 不在,在直译中的意思是“不在”或(因为在我们正在考虑的情况下翻译是合适的)-“不包含在”。 所以,就像前面的例子一样,我们有两个关系方案(R1 和R.2),大约由下式给出: R1 (关键,...)和 R2 (钥匙,...); 如您所见,在这些关系的属性中再次设置了关键属性。 因此,我们得到以下形式来表示结构化查询语言中的差异操作: 选择* 从 R1 其中 关键 不在 (选择 关键 从 R2); 因此,只有关系 R 的那些元组1,其键不包含在关系 R 的键列表中2. 如果我们从字面上考虑这个符号,那么实际上从关系 R1 “减去”比率 R2. 从这里我们得出结论,这个算子中的选择条件写得是正确的(毕竟定义了两个关系的差异),并且在执行交集操作的情况下使用键是完全合理的. 我们见过的“关键法”的两种用法是最常见的。 这结束了对在表示关系的运算符的构造中使用键的研究。 关系代数的所有剩余二元运算都以其他方式编写。 4.笛卡尔积运算 正如我们在之前的讲座中所记得的那样,两个关系操作数的笛卡尔积由属性上元组的所有可能的命名值对组成。 因此,在结构化查询语言中,笛卡尔积运算是使用交叉连接实现的,用关键字表示 交叉连接,字面意思是“交叉连接”或“交叉连接”。 在结构化查询语言中表示笛卡尔积运算的结构中只有一个 Select 运算符,其形式如下: 选择* 从 R1 交叉连接 R2 在这里1 和R.2 - 初始关系操作数的名称。 选项 交叉连接 确保生成的关系将包含与所有关系元组对 R 对应的所有属性(全部,因为运算符的第一行有“*”号)1 和R.2. 记住笛卡尔积运算实现的一个特征是非常重要的。 这个特性是笛卡尔积二元运算定义的结果。 回忆一下: r4(S4) = r1(S1)xr2(S2) = {t(小号1 ∪小号2) | t[小号1] ε r1 &t(S2) ε r2}, 小号1 ∩S2=∅; 从上面的定义可以看出,元组对是用必然不相交的关系方案形成的。 因此,在使用 SQL 结构化查询语言工作时,总是规定初始操作数关系不应具有匹配的属性名称。 但是如果这些关系仍然具有相同的名称,则可以使用属性重命名操作轻松解决当前的情况,即在这种情况下,您只需要使用选项 as, 前面已经提到了。 让我们考虑一个示例,在该示例中,我们需要找到具有某些相同属性名称的两个关系的笛卡尔积。 因此,给定以下关系: R1 (A, B), R2 (公元前); 我们看到 R 属性1.B 和 R2.B 具有相同的名称。 考虑到这一点,以结构化查询语言实现此笛卡尔积运算的 Select 语句将如下所示: 选择 一个,R1.B as B1, 右2.B as B2、C 从 R1 交叉连接 R2; 因此,使用重命名选项 as,机器将不会对两个原始操作数关系的匹配名称产生“问题”。 5.内连接操作 乍一看,我们在自然连接操作之前考虑内连接操作可能看起来很奇怪,因为当我们进行二元操作时,一切都相反。 但是通过分析结构化查询语言中的运算表达式,可以得出自然联接运算是内联接运算的一种特殊情况的结论。 这就是为什么按这个顺序考虑这些操作是合理的。 所以,首先,让我们回顾一下我们之前经历过的内连接操作的定义: r1(S1) X P r2(S2) = σ (r1 xr2), 小号1 ∩ S2 = ∅。 对我们来说,在这个定义中,所考虑的关系操作数 S 的方案尤为重要1 和S2 不得相交。 要在结构化查询语言中实现内连接操作,有一个特殊的选项 内连接,从英文直译为“inner join”或“inner join”。 内部连接操作中的 Select 语句将如下所示: 选择* 从 R1 内连接 R2; 在这里,和以前一样,R1 和R.2 - 初始关系操作数的名称。 在执行此操作时,必须不允许关系操作数的方案交叉。 6.自然加入操作 正如我们已经说过的,自然连接操作是内连接操作的一个特例。 为什么? 是的,因为在自然连接的作用过程中,原始操作数关系的元组是根据特殊条件连接起来的。 即,在关系操作数的交集处元组相等的条件下,而在内部连接操作的作用下,这种情况是不允许的。 由于我们正在考虑的自然连接操作是内连接操作的一种特殊情况,因此使用与之前考虑的操作相同的选项来实现它,即选项 内连接. 但是由于在为自然连接操作编译 Select 运算符时,还需要考虑原始操作数关系的元组在其模式的交集处相等的条件,那么除了指定的选项外,关键字被申请;被应用 on. 从英文翻译过来,字面意思是“on”,相对于我们的意思,可以翻译为“subject to”。 执行自然连接操作的 Select 语句的一般形式如下: 选择* 从 关系名称 1 内连接 关系名称 2 on 元组相等条件; 考虑这样一个例子。 给定两个关系: R1 (A, B, C), R2 (B、C、D); 这些关系的自然连接操作可以使用以下运算符来实现: 选择 一个,R1.B、R1.C、D 从 R1 内连接 R2 on R1.B=R2.B 和 R1.C=R2.C 作为此操作的结果,在 Select 运算符的第一行中指定的属性,对应于在指定交点处相等的元组,将显示在结果中。 需要注意的是,这里我们指的是公共属性 B 和 C,而不仅仅是名称。 这样做的原因与实现笛卡尔积运算的原因不同,而是因为否则将不清楚它们所指的是哪种关系。 有趣的是,连接条件的使用措辞(R1.B=R2.B 和 R1.C=R2.C) 假定不允许连接的空值关系的共享属性。 这从一开始就内置在结构化查询语言系统中。 7.左外连接操作 左外连接操作的SQL结构化查询语言表达式是通过替换关键字得到自然连接操作的实现 内 每个关键字 左外. 因此,在结构化查询的语言中,这个操作将被写成如下: 选择* 从 关系名称 1 左外连接 关系名称 2 on 元组相等条件; 8.右外连接操作 结构化查询语言中右外连接操作的表达式是通过替换关键字执行自然连接操作得到的 内 每个关键字 右外. 所以,我们得到在SQL结构化查询语言中,右外连接的操作会写成如下: 选择* 从 关系名称 1 右外连接 关系名称 2 on 元组相等条件; 9. 全外连接操作 与前两种情况一样,完全外连接操作的结构化查询语言表达式是通过替换关键字从自然连接操作的表达式中获得的 内 每个关键字 全外. 因此,在结构化查询语言中,这个操作将被写成如下: 选择* 从 关系名称 1 全外连接 关系名称 2 on 元组相等条件; 将这些选项内置到 SQL 结构化查询语言的语义中非常方便,因为否则每个程序员都必须独立输出它们并将它们输入到每个新数据库中。 4.使用子查询 从所涵盖的材料中可以理解,结构化查询语言中的“子查询”概念是一个基本概念,应用范围相当广泛(有时,顺便说一下,它们也被称为 SQL 查询。确实,编程和实践使用数据库表明编译子查询系统来解决各种相关任务 - 与处理结构化信息的其他一些方法相比,这项活动更有价值。因此,让我们考虑一个示例来更好地理解子查询的操作,它们的编译和使用。 假设有以下某个数据库的片段,可以在任何教育机构中使用: 项目 (项目代码, 项目名); 学生 (记录簿编号, 全名); 会议 (科目代码、年级书号, 年级); 让我们制定一个 SQL 查询,该查询返回一条语句,该语句指示学生的成绩簿编号、姓氏和首字母缩写,以及名为“数据库”的科目的成绩。 大学需要始终及时地接收此类信息,因此以下查询可能是使用此类数据库的最流行的编程单元。 为方便起见,我们另外假设“姓氏”、“名字”和“Patronymic”属性不允许 Null 值且不为空。 这个要求是非常容易理解和合乎逻辑的,因为一个新生的数据首先被输入到任何教育机构的数据库中,就是他的姓氏、名字和父名的数据。 不用说,在这样的数据库中不可能有一个条目包含学生的数据,但同时他的名字是未知的。 请注意,“Items”关系模式的“Item Name”属性是一个键,因此从定义来看(稍后会详细介绍),所有项目名称都是唯一的。 这在不解释密钥的表示的情况下也是可以理解的,因为在教育机构中教授的所有科目都必须具有并且具有不同的名称。 现在,在我们开始编译运算符本身的文本之前,我们将介绍两个对我们有用的函数。 首先,我们需要函数 修剪, 写成 Trim("string"),即这个函数的参数是一个字符串。 这个函数有什么作用? 它们在此行的开头和结尾返回参数本身,不带空格,即,使用此函数,例如,在以下情况下:Trim ("Bogucharnikov") 或 Trim ("Maksimenko"),当参数之后或之前值得一些额外的空间。 其次,还需要考虑 Left 函数,它写成 Left (string, number),即已经有两个参数的函数,其中一个和以前一样是字符串。 它的第二个参数是一个数字,它表示应该在结果中输出字符串左侧的多少个字符。 例如运行结果: 左(“米哈伊尔,1”)+“。” + 左(“齐诺维耶维奇,1”) 将是首字母“M.Z.” 我们将在查询中使用此功能是为了显示学生的姓名首字母。 所以,让我们开始编译所需的查询。 首先,让我们做一个小的辅助查询,然后我们在主查询中使用它: 选择 成绩册编号,年级 从 会议 其中 商品代码 = (选择 项目代码 从 对象 其中 项目名称 = “数据库”) as “估计”数据库“; 在这里使用 as 选项意味着我们已将此查询别名为“数据库估计”。 我们这样做是为了方便进一步处理此请求。 接下来,在这个查询中,一个子查询: 选择 项目代码 从 对象 其中 项目名称=“数据库”; 允许您从关系“会话”中选择与所考虑的主题相关的元组,即与数据库相关的元组。 有趣的是,这个内部子查询只能返回一个值,因为“Item Name”属性是“Items”关系的键,即它的所有值都是唯一的。 整个查询“Scores“Database”允许您从“Session”关系数据中选择满足子查询中指定条件的那些学生(他们的成绩簿编号和成绩),即有关称为“Database”的主题的信息。 现在我们将使用已经收到的结果发出主要请求。 选择 学生。 记录簿编号, 修剪 (姓氏) + " " + 左 (姓名,1)+“。” + 左 (父名,1)+“。”as 全名,估计“数据库”。 年级 从 学生 内连接 ( 选择 成绩册编号,年级 从 会议 其中 商品代码 = (选择 项目代码 从 对象 其中 项目名称 = “数据库”) )as “估计”数据库“。 on 学生。 成绩册# =“数据库”成绩。 记录簿编号。 因此,首先我们列出查询完成后需要显示的属性。 应该提到的是,“成绩簿编号”属性来自学生关系,从那里 - 属性“姓氏”、“名字”和“Patronymic”。 没错,最后两个属性没有完全推导出来,而只是第一个字母。 我们还提到了我们之前输入的“数据库分数”查询中的“分数”属性。 我们从“学生”关系的内部连接和查询“数据库成绩”中选择所有这些属性。 我们可以看到,这个内连接是我们在记录簿数量相等的情况下采取的。 作为这种内连接操作的结果,成绩被添加到学生关系中。 需要注意的是,由于条件属性“Last Name”、“First Name”和“Patronymic”不允许Null-values且不为空,因此返回属性“Name”的计算公式(修剪 (姓氏) + " " + 左 (姓名,1)+“。” + 左 (父名,1)+“。”as 全名),分别不需要额外的检查,是简化的。 第7讲基本关系 众所周知,数据库就像一种容器,其主要目的是存储以关系形式呈现的数据。 您需要知道,根据其性质和结构,关系分为: 1) 基本关系; 2) 虚拟关系. 基本视图关系只包含独立的数据,不能用任何其他数据库关系来表示。 在商业数据库管理系统中,基本关系通常简称为 桌子 与对应于虚拟关系概念的表示相反。 在本课程中,我们将仅详细讨论基本关系、主要技术和使用它们的原则。 一、基本数据类型 数据类型,如关系,分为 基本的 и 虚拟. (稍后我们将讨论虚拟数据类型;我们将用一个单独的章节来讨论这个主题。) 基本数据类型 - 这些是最初在数据库管理系统中定义的任何数据类型,即默认存在的数据类型(与用户定义的数据类型相反,我们将在传递基本数据类型后立即对其进行分析)。 在开始考虑实际的基本数据类型之前,我们先列出一般有哪些数据类型: 1) 数值数据; 2)逻辑数据; 3)字符串数据; 4) 定义日期和时间的数据; 5) 识别数据。 默认情况下,数据库管理系统引入了几种最常见的数据类型,每种数据类型都属于列出的数据类型之一。 让我们打电话给他们。 1。 该 数值 数据类型区分: 1) 整数。 该关键字通常表示整数数据类型; 2) Real,对应真实的数据类型; 3)十进制(n,m)。 这是十进制数据类型。 另外,符号中n是固定该数的总位数的数,m表示小数点后有多少个字符。 4) Money or Currency,专门为方便货币数据类型的数据表示而引入。 2。 该 合乎逻辑的 数据类型通常只分配一种基本类型,这就是逻辑。 3. 细绳 数据类型有四种基本类型(当然是最常见的): 1) 比特(n)。 这些是具有固定长度 n 的位串; 2) Varbit(n)。 这些也是位串,但可变长度不超过 n 位; 3) 字符(n)。 这些是具有恒定长度 n 的字符串; 4) Varchar(n)。 这些是字符串,可变长度不超过 n 个字符。 4.类型 日期和时间 包括以下基本数据类型: 1) 日期——日期数据类型; 2) Time - 表示一天中时间的数据类型; 3) 日期时间是一种同时表示日期和时间的数据类型。 5. 鉴定 数据类型仅包含数据库管理系统中默认包含的一种类型,即 GUID(Globally Unique Identifier)。 需要注意的是,所有基本数据类型都可以有不同数据表示范围的变体。 举个例子,四字节整数数据类型的变体可以是八字节(bigint)和两字节(smallint)数据类型。 下面我们分别谈谈基本的 GUID 数据类型。 这种类型旨在存储所谓的全局唯一标识符的十六字节值。 当调用特殊的内置函数时,会自动生成此标识符的所有不同值 新标识(). 该名称来自完整的英文短语 New Identification,字面意思是“新标识符值”。 在特定计算机上生成的每个标识符值在所有制造的计算机中都是唯一的。 GUID 标识符特别用于组织数据库复制,即在创建某些现有数据库的副本时。 数据库开发人员可以将此类 GUID 与其他基本类型一起使用。 GUID 类型和其他基本类型之间的中间位置被另一种特殊的基本类型占用 - 类型 柜台. 使用特殊关键字来指定这种类型的数据。 计数器(x0, Δx),字面意思是从英语翻译过来的,意思是“柜台”。 参数 x0 设置初始值,并且 Δx - 增量步长。 这个Counter类型的值必然是整数。 应该注意的是,使用这种基本数据类型包括许多非常有趣的特性。 例如,此 Counter 类型的值未设置,正如我们在处理所有其他数据类型时所习惯的那样,它们是按需生成的,就像全局唯一标识符类型的值一样。 同样不寻常的是,计数器类型只能在定义表时指定,而且只有这样! 此类型不能在代码中使用。 您还需要记住,在定义表时,只能为一列指定计数器类型。 插入行时会自动生成计数器数据值。 而且,这一代是不重复进行的,因此计数器将始终唯一标识每一行。 但这在处理包含计数器数据的表时会带来一些不便。 例如,如果表给定的关系中的数据发生变化并且必须删除或交换它们,则计数器值很容易“混淆卡片”,尤其是在没有经验的程序员工作的情况下。 让我们举一个例子来说明这种情况。 给出表示某种关系的下表,其中输入了四行: 计数器自动给每个新行一个唯一的名称。 现在让我们从表格中删除第二行和第四行,然后再添加一行。 这些操作将导致源表的以下转换: 因此,计数器删除了第二行和第四行以及它们的唯一名称,并且没有像人们预期的那样将它们“重新分配”到新行。 此外,数据库管理系统绝不允许您手动更改计数器的值,就像它不允许您同时在一张表中声明多个计数器一样。 通常,计数器用作代理项,即表中的人工键。 有趣的是,一个四字节计数器的唯一值以每秒一个值的生成速率将持续 100 多年。 让我们展示它是如何计算的: 1 年 = 365 天 * 24 小时 * 60 秒 * 60 秒 < 366 天 * 24 小时 * 60 秒 * 60 秒 < 225 与。 1 秒 > 2-25 一年。 24*8 值/1个值/秒=232 c > 27 年 > 100 年。 2.自定义数据类型 自定义数据类型与所有基本类型的不同之处在于它最初并未内置到数据库管理系统中,也未声明为默认数据类型。 这种类型可以由任何用户和数据库程序员根据自己的要求和要求创建。 因此,用户定义的数据类型是某个基本类型的子类型,也就是说,它是对允许值集有一些限制的基本类型。 在伪代码表示法中,使用以下标准语句创建自定义数据类型: 创建子类型 子类型名称 Type 基本类型名称 As 子类型约束; 因此,在第一行中,我们必须指定新的、用户定义的数据类型的名称,在第二行中 - 我们将现有的基本数据类型中的哪些作为模型,创建我们自己的,最后,在第三行中- 我们需要添加到对基本数据类型的值集的现有限制的那些限制 - 样本。 子类型约束被写成依赖于所定义子类型名称的条件。 为了更好地理解 Create 语句的工作原理,请考虑以下示例。 假设我们需要创建自己的专用数据类型,例如,在邮件中工作。 这将是处理邮政编码等数据的类型。 我们的数字与普通的十进制六位数字不同,因为它们只能是正数。 让我们编写一个运算符来创建我们需要的子类型: 创建子类型 邮编 Type 十进制 (6, 0) As 邮政编码 > 0。 为什么我们选择小数(6, 0)? 回顾索引的通常形式,我们看到这样的数字必须由从 XNUMX 到 XNUMX 的六个整数组成。 这就是我们将十进制类型作为基本数据类型的原因。 奇怪的是,一般情况下,施加在基本数据类型上的条件,即子类型约束,可能包含逻辑连接词 not,and,or,并且通常是任意复杂性的表达式。 以这种方式定义的自定义数据子类型可以与其他基本数据类型一起在程序代码中以及在表列中定义数据类型时自由使用,即在使用它们时基本数据类型和用户数据类型完全相等。 在可视化开发环境中,它们与其他基本数据类型一起出现在有效类型列表中。 在设计我们自己的新数据库时,我们可能需要未记录的(用户定义的)数据类型的可能性非常高。 事实上,默认情况下,只有最常见的数据类型被缝合到数据库管理系统中,分别适用于解决最常见的任务。 在编译主题数据库时,几乎不可能不设计自己的数据类型。 但是,奇怪的是,以相同的概率,我们可能需要删除我们创建的子类型,以免使代码混乱和复杂。 为此,数据库管理系统通常内置有一个特殊的运算符。 下降,这意味着“删除”。 此运算符用于删除不必要的自定义类型的一般形式如下: 掉落亚型 自定义类型的名称; 对于足够通用的子类型,通常建议使用自定义数据类型。 3. 默认值 数据库管理系统可能具有创建任意默认值的能力,或者也称为默认值。 这种操作在任何编程环境中都有相当大的权重,因为几乎在任何任务中都可能需要引入常量、不可变的默认值。 为了在数据库管理系统中创建默认值,我们使用了从用户定义数据类型的通道中已经熟悉的功能 创建. 仅在创建默认值的情况下,还使用了附加关键字 默认,这意味着“默认”。 换句话说,要在现有数据库中创建默认值,您必须使用以下语句: 创建默认值 默认名称 As 常量表达式; 很明显,在应用此运算符时,您需要写出我们想要作为默认值或表达式的值或表达式来代替常量值。 而且,当然,我们需要决定以什么名称方便我们在数据库中使用它,并将这个名称写在操作符的第一行。 请注意,在这种特殊情况下,此 Create 语句遵循 Microsoft SQL Server 系统中内置的 Transact-SQL 语法。 那么我们得到了什么? 我们已经推断出默认值是存储在数据库中的命名常量,就像它的对象一样。 在可视化开发环境中,默认值出现在突出显示的默认值列表中。 这是创建默认值的示例。 假设为了我们的数据库的正确操作,需要一个值函数在其中具有无限生命周期的含义。 然后你需要在这个数据库的值列表中输入满足这个要求的默认值。 这可能是必要的,如果只是因为每次在代码文本中遇到这种相当繁琐的表达,再写出来会非常不方便。 这就是为什么我们将使用上面的 Create 语句来创建一个默认值,其含义是无限的生命周期。 创建默认值 “没有时间限制” As ‘9999-12-31 23: 59:59’ 这里也使用了 Transact-SQL 语法,根据该语法,将日期时间常量(本例中为 '9999-12-31 23:59:59')的值写成某个方向的字符串。 字符串作为日期时间值的解释由使用字符串的上下文决定。 例如,在我们的特定情况下,首先将年份的限制值写入常量行,然后写入时间。 然而,尽管它们很有用,但有时也需要删除默认值,如用户定义的数据类型。 数据库管理系统通常有一个特殊的内置谓词,类似于删除不再需要的更多用户定义数据类型的运算符。 这是一个谓词 下降 运算符本身如下所示: 删除默认值 默认名称; 4. 虚拟属性 数据库管理系统中的所有属性都被划分(通过与关系的绝对类比)分为基本属性和虚拟属性。 所谓 基本属性 是需要多次使用的存储属性,因此建议保存。 反过来, 虚拟属性 不是存储的,而是计算的属性。 这是什么意思? 这意味着所谓的虚拟属性的值并没有实际存储,而是通过给定的公式通过基础属性即时计算出来的。 在这种情况下,计算的虚拟属性的域是自动确定的。 我们举一个定义关系的表的例子,其中两个属性是普通的、基本的,第三个属性是虚拟的。 它将根据专门输入的公式计算。 因此,我们看到属性“Weight Kg”和“Price Rub per Kg”是基本属性,因为它们具有普通值并且存储在我们的数据库中。 但是属性“成本”是一个虚拟属性,因为它是由它的计算公式设定的,不会实际存储在数据库中。 有趣的是,由于它们的性质,虚拟属性不能采用默认值,一般来说,虚拟属性的默认值的概念是没有意义的,因此不适用。 而且您还需要注意,虽然虚拟属性的域是自动确定的,但有时需要将计算值的类型从现有的一种更改为另一种。 为此,数据库管理系统的语言有一个特殊的 Convert 谓词,借助它可以重新定义计算表达式的类型。 Convert 就是所谓的显式类型转换函数。 它是这样写的: 转化率 (数据类型,表达式); 作为 Convert 函数的第二个参数的表达式将被计算并作为此类数据输出,其类型由函数的第一个参数指示。 考虑一个例子。 假设我们需要计算表达式“2 * 2”的值,但我们需要输出的不是整数“4”,而是字符串。 为了完成这个任务,我们编写了下面的转换函数: 转化率 (字符(1),2 * 2)。 因此,我们可以看到 Convert 函数的这种表示法将准确地给出我们需要的结果。 5.键的概念 在声明基本关系的模式时,可以给出多个键的声明。 我们以前遇到过很多次。 最后,是时候更详细地讨论什么是关系键,而不仅限于一般短语和近似定义。 所以,让我们给出一个关系键的严格定义。 关系架构键 是原始模式的子模式,由一个或多个为其声明的属性组成 唯一性条件 关系元组中的值。 为了理解唯一性条件是什么,或者,也称为, 唯一约束,让我们从元组的定义和将元组投影到子电路上的一元运算开始。 让我们把它们带来: t = t(S) = {t(a) | a ∈ def( t) ⊆ S} - 元组的定义, t(S) [S' ] = {t(a) | a ∈ def (t) ∩ S'},S' ⊆ S 是一元投影运算的定义; 很明显,元组在子模式上的投影对应于表行的子字符串。 那么,关键属性唯一性约束究竟是什么? 关系 S 方案的键 K 的声明导致以下不变条件的公式化,如我们已经说过的,称为: 唯一性约束 并表示为: 库存 < K → S > r(S): Inv < K → S > r(S) = ∀t1,T2 ε r (t 1[K]=t2 [K] → t 1(S) = 吨2(S)), K ⊆ S; 所以,这个键 K 的唯一性约束 Inv < K → S > r(S) 意味着如果任意两个元组 t1 иŧ2,属于关系 r(S),在映射到键 K 上是相等的,那么这必然需要这两个元组的相等性以及在关系 S 的整个方案上的投影。换句话说,所有值属于关键属性的元组是唯一的,它们的关系是唯一的。 关系键的第二个重要要求是 冗余要求. 这是什么意思? 此要求意味着不需要严格的密钥子集是唯一的。 在直观的层面上,很明显,关键属性是唯一且准确地标识关系的每个元组的关系属性。 例如,在表格给出的以下关系中: 关键属性是“Gradebook #”属性,因为不同的学生不能有相同的成绩册编号,即该属性受唯一约束。 有趣的是,在任何关系的模式中,都可能出现各种键。 我们列出了主要的键类型: 1) 简单的钥匙 是由一个且没有更多属性组成的键。 例如,在特定科目的试卷中,一个简单的关键字就是信用卡号,因为它可以唯一地识别任何学生; 2) 复合键 是由两个或多个属性组成的键。 例如,教室列表中的复合键是建筑物编号和教室编号。 毕竟,不可能用这些属性中的一个来唯一地识别每个观众,而用他们的整体来做到这一点是很容易的,也就是说,用一个复合键; 3) 超级钥匙 是任何键的任何超集。 因此,关系本身的模式当然是一个超键。 由此我们可以得出结论,理论上任何关系都至少有一个键,并且可能有多个键。 但是,声明一个超级键代替普通键在逻辑上是非法的,因为它涉及放松自动强制执行的唯一性约束。 毕竟,超级密钥虽然具有唯一性,但不具有非冗余性; 4) 首要的关键 只是在定义基本关系时首先声明的键。 重要的是声明一个且只有一个主键。 此外,主键属性永远不能取空值。 在伪代码条目中创建基本关系时,表示主键 主键 括号中是属性的名称,也就是这个键; 5) 候选键 是在主键之后声明的所有其他键。 候选键和主键之间的主要区别是什么? 首先,可以有多个候选键,而主键,如上所述,只能是一个。 其次,如果主键的属性不能取 Null 值,那么这个条件就不会强加给候选键的属性。 在伪代码中,当定义一个基本关系时,候选键是使用单词声明的 候选键 然后在括号中,与声明主键的情况一样,指示属性的名称,即给定的候选键; 6) 外键 是在基本关系中声明的键,它还引用相同或某些其他基本关系的主键或候选键。 在这种情况下,外键引用的关系称为引用(或 父母) 态度。 包含外键的关系称为 孩子. 在伪代码中,外键表示为 外键,在这些词之后的括号中,表示该关系的属性名称,即外键,然后写入关键字 引用 (“引用”)并指定基本关系的名称和该特定外键引用的属性的名称。 此外,在创建基本关系时,对于每个外键,都会写入一个条件,称为 参照完整性约束,但我们稍后会详细讨论。 讲座#8 本讲座的主题将是对基本关系创建运算符的相当详细的讨论。 我们将在伪代码记录中分析算子本身,分析其所有组件及其工作,分析修改方法,即改变基本关系。 1.元语言符号 在用伪代码描述用于编写基本关系创建运算符的句法结构时,使用了各种方法。 元语言符号. 这些是各种开括号和右括号,点和逗号的各种组合,总之,每个符号都有自己的含义,使程序员更容易编写代码。 让我们介绍和解释在基本关系设计中最常用的主要元语言符号的含义。 所以: 1) 元语言字符“{}”。 花括号中的句法结构是 强制性 句法单元。 在定义基本关系时,所需的元素例如是基本属性; 如果不声明基本属性,就无法设计任何关系。 因此,在用伪代码编写基关系创建运算符时,基属性列在花括号中; 2)元语言符号“[]”。 在这种情况下,情况正好相反:方括号中的语法结构表示 可选的 语法元素。 基础关系创建运算符中的可选句法单元依次是主键、候选键和外键的虚拟属性。 当然,这里也有一些微妙之处,但我们稍后会讨论它们,当我们直接进行用于创建基本关系的运算符的设计时; 3)元语言符号“|”。 这个符号的字面意思是 “或者”,就像数学中的类比符号。 使用这个元语言符号意味着一个人必须在两个或多个分别被这个符号分隔的结构之间进行选择; 4)元语言符号“...”。 紧接在任何句法单元之后的省略号表示可能性 重复 元语言符号之前的这些句法元素; 5) 元语言符号“,..”。 该符号的含义与前一个符号几乎相同。 仅当使用元语言符号“,..”时, 重申 出现句法结构 被逗号隔开这通常更方便。 考虑到这一点,我们可以讨论以下两种句法结构的等价性: 单位[,单位]... и 单元,.. ; 2.在伪代码条目中创建基本关系的示例 现在我们已经阐明了用伪代码编写基本关系创建运算符时使用的主要元语言符号的含义,我们可以继续实际考虑这个运算符本身。 从上面的参考资料可以理解,在伪代码条目中用于创建基本关系的操作符包括基本和虚拟属性、主键、候选键和外键的声明。 此外,如上面将显示和解释的,该运算符还包括属性值约束和元组约束,以及所谓的参照完整性约束。 前两个约束,即属性值约束和元组约束,声明在特殊保留字之后 查. 参照完整性约束可以有两种类型: 更新时,这意味着“更新时”,并且 删除时,这意味着“删除时”。 这是什么意思? 这意味着当更新或删除外键引用的关系的属性时,必须保持状态完整性。 (我们稍后会详细讨论。) 基础关系创建算子本身就是我们已经研究过的——算子 创建, 只为建立基本关系,添加关键字 表 (“态度”)。 而且,当然,由于关系本身更大,并且包括所有前面讨论过的结构,以及新的附加结构,因此 create 运算符将非常令人印象深刻。 因此,让我们用伪代码编写用于创建基本关系的运算符的一般形式: 创建表格 基本关系名称 { 基本属性名称 基本属性值类型 查 (属性值限制) {空 | 不为空} 默认 (默认值) },.. [虚拟属性名称 as (计算公式) ],.. [,查 (元组约束)] [,主键 (属性名称,..)] [,候选键 (属性名称,..)]... [,外键 (属性名称,..) 引用 参考关系名称(属性名称,..) 更新时 { 限制 | 级联 | 置空} 删除 { 限制 | 级联 | 置空} ] ... 因此,我们看到可以声明几个基本属性和虚拟属性、候选键和外键,因为在相应的句法结构之后有一个元语言符号“,..” 在主键声明之后,这个符号就不存在了,因为如前所述的基本关系只允许一个主键。 接下来,让我们仔细看看声明机制。 基本属性. 在描述基础关系创建算子中的任何属性时,一般情况下,会指定其名称、类型、对其值的限制、Null-values 有效性标志和默认值。 很容易看出,一个属性的类型和它的值约束决定了它的域,即字面意思是那个特定属性的有效值的集合。 属性值限制 写成依赖于属性名称的条件。 下面是一个小例子,可以让这个材料更容易理解: 创建表格 基本关系名称 课程 整数 查 (1 <= 课程和课程 <= 5; 在这里,条件“1 <= Heading and Heading <= 5”与整数数据类型的定义一起真正完全限定了属性的允许值集,即字面意思是它的域。 Null 值允许标志(Null | not Null)禁止(非 Null)或者相反,允许(Null)属性值中出现 Null 值。 以刚刚讨论的示例为例,应用 Null-validity 标志的机制如下: 创建表格 基本关系名称 课程 整数 查 (1 <= 课程和课程 <= 5); 不为空; 因此,学生的课程号不能为空,不能为数据库编译器所知,不能不存在。 默认值(默认 (默认值)) 用于将元组插入关系时,如果属性值没有在插入语句中显式设置。 有趣的是,默认值也可以是 Null 值,只要该特定属性的 Null 值被声明为有效即可。 现在考虑定义 虚拟属性 在基本关系创建运算符中。 正如我们之前所说,设置虚拟属性包括通过其他基本属性设置计算公式。 让我们考虑一个声明虚拟属性“Cost Rub”的示例。 根据基本属性“重量公斤”和“每公斤价格”的公式形式。 创建表格 基本关系名称 重量,公斤 基本属性值类型 重量 Kg 查 (属性值Weight Kg的限制) 不为空 默认 (默认值) 价格,擦。 每公斤 基本属性 Price Rub 的值类型。 每公斤 查 (Price Rub.per Kg 属性值的限制) 不为空 默认 (默认值) ... 成本,擦。 as (重量公斤 * 价格摩擦。每公斤) 早些时候,我们查看了属性约束,它们被写成依赖于属性名称的条件。 现在考虑创建基本关系时声明的第二种约束,即 元组约束. 什么是元组约束,它与属性约束有何不同? 元组约束也写成依赖于基本属性名的条件,但只有在元组约束的情况下,条件才能同时依赖于多个属性名。 考虑一个示例,说明使用元组约束的机制: 创建表格 基本关系名称 最小重量公斤 基础属性的值类型 min Weight Kg 查 (属性值min Weight Kg的限制) 不为空 默认 (默认值) 最大重量公斤 基础属性的值类型 max Weight Kg 查 (属性值max Weight Kg的限制) 不为空 默认 (默认值) 查 (0 < 最小重量 Kg 和 最小重量公斤 < 最大重量公斤); 因此,对元组应用约束相当于用元组的值替换属性名称。 让我们继续考虑基本关系创建运算符。 一旦声明,基本和虚拟属性可能会或可能不会被声明。 按键:主要、候选和外部。 正如我们之前所说,在另一个(或相同)基本关系中对应于第一个关系上下文中的主键或候选键的基本关系的子模式称为 外键. 外键代表 连杆机构 一些关系的元组在其他关系的元组上,即存在与已经提到的所谓的强加相关的外键声明 参照完整性约束. (这个约束将是下一节课的重点,因为状态完整性(即完整性约束强制执行的完整性)对于基础关系和整个数据库的成功至关重要。) 反过来,声明主键和候选键会对我们之前讨论过的基本关系模式施加适当的唯一性约束。 最后,应该说一下删除基本关系的可能性。 通常在数据库设计实践中,有必要删除旧的不必要的关系,以免混淆程序代码。 这可以使用已经熟悉的运算符来完成 下降. 在其完整的一般形式中,基本关系删除运算符如下所示: 放下桌子 基础关系的名称; 3. 国家完整性约束 完整性约束 关系数据对象 作为 就是所谓的数据不变量。 同时,完整性应该有把握地与安全性区分开来,而安全性又意味着保护数据免遭未经授权的访问,从而泄露、修改或破坏数据。 通常,对关系数据对象的完整性约束进行分类 按层级 这些相同的关系数据对象(关系数据对象的层次结构是一系列嵌套概念:“属性-元组-关系-数据库”)。 这是什么意思? 这意味着完整性约束取决于: 1)在属性级别——从属性值; 2)在元组层面——来自元组的值,即来自几个属性的值; 3)在关系层面——来自一个关系,即来自几个元组; 4)在数据库级别 - 从几个关系。 因此,现在我们只需要更详细地考虑对上述每个概念的状态的完整性约束。 但首先,让我们给出对状态完整性约束的程序性和声明性支持的概念。 因此,对完整性约束的支持可以有两种类型: 1) 程序,即通过编写程序代码创建; 2) 声明性的,即通过为上述每个嵌套概念声明某些限制来创建。 对完整性约束的声明性支持是在用于创建基本关系的 Create 语句的上下文中实现的。 让我们更详细地讨论一下。 让我们从关系数据对象的层次阶梯的底部开始考虑一组限制,即从属性的概念开始。 属性级别约束 它包括: 1) 对属性值类型的限制。 例如,值的整数条件,即来自前面讨论的基本关系之一的“课程”属性的整数条件; 2) 属性值约束,写成依赖于属性名称的条件。 例如,分析与上一段相同的基本关系,我们看到在该关系中也存在使用选项对属性值的约束 查, IE。: 查 (1 <= 课程和课程 <= 5); 3) 属性级约束包括由众所周知的有效性标志(Null)定义的 Null 值约束,或者相反,Null 值的不可接受性(非 Null)。 正如我们前面提到的,前两个约束定义了属性的域约束,即其定义集的值。 此外,根据关系数据对象的层次阶梯,我们需要谈谈元组。 所以, 元组级约束 简化为一个元组约束,并写成一个依赖于关系模式的几个基本属性名称的条件,即这种状态完整性约束比类似的约束要小得多,也简单得多,只对应于属性。 再一次,回忆一下我们之前经历过的基本关系的例子会很有用,它有我们现在需要的元组约束,即: 查 (0 < 最小重量 Kg 和 最小重量公斤 < 最大重量公斤); 最后,在状态完整性约束的背景下,最后一个重要的概念是关系级别的概念。 正如我们之前所说, 关系级别约束 包括限制初级(主键) 和候选人 (候选键) 键。 奇怪的是,对数据库施加的限制不再是状态完整性约束,而是参照完整性约束。 4. 参照完整性约束 因此,数据库级约束包括外键参照完整性约束(外键)。 当我们在创建基本关系和外键时讨论参照完整性约束时,我们已经简要提到了这一点。 现在是时候更详细地讨论这个概念了。 正如我们之前所说,声明的基本关系的外键是指其他(最常见的)基本关系的主键或候选键。 回想一下,在这种情况下,外键引用的关系称为 参考 или 父母的,因为它有点“产生”引用基础关系中的一个属性或多个属性。 反过来,包含外键的关系称为 孩子,也有明显的原因。 是什么 参照完整性约束? 并且它在于子关系的外键的每个值都必须与父关系的任何键的值对应,除非外键的值在任何属性中都包含Null值。 违反此条件的子关系的元组称为 绞刑. 事实上,如果子关系的外键引用了一个在父关系中实际上并不存在的属性,那么它就不会引用任何东西。 正是这些情况必须以各种可能的方式避免,这意味着要保持参照完整性。 但是,知道没有数据库将允许创建悬空元组,开发人员确保数据库中没有最初的悬空元组,并且所有可用的键都引用父关系的一个非常真实的属性。 然而,在数据库运行期间,有些情况下已经形成了悬空元组。 这些情况是什么? 众所周知,当从父关系中删除元组或更新父关系的元组的键值时,可能会违反参照完整性,即可能出现悬空元组。 为了在声明外键值时排除它们发生的可能性,指定以下之一: 三 可得到 规则 保持参照完整性,在更新父关系中的键值时相应地应用(即,正如我们前面提到的, 更新时) 或从父关系中删除元组时 (删除时)。 应该注意的是,由于显而易见的原因,向父关系添加新元组不能破坏参照完整性。 毕竟,如果这个元组只是添加到基础关系中,之前没有属性可以引用它,因为它不存在! 那么这三个用于维护数据库中的引用完整性的规则是什么? 让我们列出它们。 1. 限制或 限制规则. 如果在设置我们的基本关系时,在引用完整性约束中声明外键时,我们应用了维护它的这条规则,那么如果这个元组是被子关系的至少一个元组引用,即操作 限制 陈词滥调禁止执行任何可能导致出现挂起元组的操作。 我们用下面的例子来说明这个规则的应用。 给定两个关系: 父母的态度 子女关系 我们看到子关系元组 (2,...) 和 (2,...) 引用父关系元组 (..., 2),子关系元组 (3,...) 引用( ..., 3) 父母的态度。 子关系的元组 (100,...) 是悬空的并且无效。 这里,只有父关系元组 (..., 1) 和 (..., 4) 允许更新键值和删除元组,因为它们没有被任何子关系的外键引用。 让我们编写用于创建基本关系的运算符,其中包括上述所有键的声明: 创建表格 父母的态度 首要的关键 整数 不为空 主键 (首要的关键) 创建表格 子女关系 外键 整数 空 外键 (外键) 引用 父关系(Primary_key) 更新限制 删除限制 2. 级联或 级联修改规则. 如果在我们的基础关系中声明外键时,我们使用了维护参照完整性的规则 级联,然后更新父关系中的一个键或从父关系中删除一个元组会导致子关系的相应键和元组自动更新或删除。 让我们看一个例子来更好地理解级联修改规则是如何工作的。 让我们从前面的例子中已经熟悉的基本关系给出: 父母的态度 и 子女关系 假设我们更新了表中定义“父关系”关系的一些元组,即将元组(..., 2)替换为元组(..., 20),即得到一个新的关系: 父母的态度 同时让在声明外键时创建我们的基础关系“子关系”的语句中,我们使用了保持参照完整性的规则 级联,即创建我们的基本关系的运算符如下所示: 创建表格 父母的态度 首要的关键 整数 不为空 主键 (首要的关键) 创建表格 子女关系 外键 整数 空 外键 (外键) 引用 父关系(Primary_key) 在更新级联 在删除级联 那么当父关系以上述方式更新时,子关系会发生什么? 它将采用以下形式: 子女关系 因此,确实,规则 级联 响应父关系的更新,提供子关系中所有元组的级联更新。 3. 设置为空或 空分配规则. 如果在创建基本关系的声明中,当声明外键时,我们应用维护参照完整性的规则 设置为空,那么更新父关系的键或从父关系中删除元组需要自动将 Null 值分配给允许 Null 值的子关系的那些外键属性。 因此,如果存在此类属性,则该规则适用。 让我们看一个我们之前已经使用过的例子。 假设我们有两个基本关系: “育儿” 子女关系 如您所见,子关系属性允许 Null 值,因此规则 设置为空 适用于这种特殊情况。 现在让我们假设元组 (..., 1) 已从父关系中删除,并且元组 (..., 2) 已更新,如前面的示例所示。 因此,父关系采用以下形式: 父母的态度 然后,考虑到在声明子关系的外键时,我们应用了保持参照完整性的规则 设置为空,子关系将如下所示: 子女关系 元组 (..., 1) 未被任何子关系键引用,因此删除它不会产生任何后果。 使用规则的基本关系创建运算符本身 设置为空 声明外键时,关系如下: 创建表格 父母的态度 首要的关键 整数 不为空 主键 (首要的关键) 创建表格 子女关系 外键 整数 空 外键 (外键) 引用 父关系(Primary_key) 更新时设置 Null 删除时设置 Null 因此,我们看到存在三个不同的维护参照完整性的规则确保在短语中 更新时 и 删除时 功能可能会有所不同。 必须记住并理解,如果这会导致违反参照完整性,即出现所谓的悬空元组,则不会执行将元组插入子关系或更新子关系的键值的操作。 在任何情况下从子关系中删除元组都不会导致违反参照完整性。 有趣的是,如果其他基本关系的外键将其某些属性称为主键,则子关系可以同时充当父关系,并具有自己的维护参照完整性的规则。 如果程序员想要确保参照完整性由上述标准规则以外的某些规则强制执行,则在所谓的触发器的帮助下提供对此类用于维护参照完整性的非标准规则的程序支持。 不幸的是,对这个概念的详细考虑并没有进入我们的讲座课程。 五、指数的概念 基本关系中键的创建会自动链接到索引的创建。 让我们定义索引的概念。 指数 - 这是一个系统数据结构,它包含一个键值的必要有序列表,其中包含指向这些值出现的关系的那些元组的链接。 数据库管理系统中有两种类型的索引: 1) 简单. 从单个属性中为基本关系的模式子模式获取一个简单的索引; 2) 合成的. 因此,复合索引是由几个属性组成的子模式的索引。 但是,除了分为简单索引和复合索引之外,在数据库管理系统中,索引还分为唯一索引和非唯一索引。 所以: 1) 独特 索引是最多引用一个属性的索引。 唯一索引一般对应关系的主键; 2) 非唯一 索引是可以同时匹配多个属性的索引。 反过来,非唯一键最常对应关系的外键。 考虑一个说明将索引划分为唯一和非唯一的示例,即考虑由表定义的以下关系: 这里分别,Primary key是关系的主键,Foreign key是外键。 很明显,在这些关系中,Primary key属性的索引是唯一的,因为它对应的是主键,即一个属性,而Foreign key属性的索引是非唯一的,因为它对应的是foreign键。 它的值“20”对应关系表的第一行和第三行。 但有时可以在不考虑键的情况下创建索引。 这是在数据库管理系统中完成的,以支持排序和搜索操作的性能。 例如,对元组中的索引值的二分搜索将在 XNUMX 次迭代中在数据库管理系统中实现。 这些信息是从哪里来的? 它们是通过简单的计算获得的,即如下: 106 =(103)2 = 220; 索引是使用我们已知的 Create 语句在数据库管理系统中创建的,但只能添加 index 关键字。 这样的运算符如下所示: 创建索引 索引名称 On 基本关系名称(属性名称,..); 在这里,我们看到熟悉的元语言符号“,..”表示重复由逗号分隔的参数的可能性,即可以在此运算符中创建对应于多个属性的索引。 如果要声明唯一索引,则在索引词前加上唯一关键字,然后基础索引关系中的整个创建语句就变成: 创建唯一索引 索引名称 On 基本关系名称(属性名称); 然后,在最一般的形式中,如果我们回顾指定可选元素的规则(元语言符号 []),基本关系中的索引创建运算符将如下所示: 创建 [唯一] 索引 索引名称 On 基本关系名称(属性名称,..); 如果你想从基础关系中删除一个已经存在的索引,使用我们也知道的 Drop 操作符: 删除索引 {基本关系名称。 索引名称},.. ; 为什么这里使用限定索引名“基础关系名.索引名”? 索引删除运算符始终使用其限定名称,因为索引名称在同一关系中必须是唯一的,但仅此而已。 6.修改基本关系 为了成功和高效地处理各种基础关系,开发人员经常需要以某种方式修改这种基础关系。 数据库设计实践中最常遇到的主要修改选项是什么? 让我们列出它们: 1) 元组的插入。 很多时候,您需要将新元组插入到已经形成的基本关系中; 2) 更新属性值。 而在编程实践中这种修改的需求比前一种更为普遍,因为当你的数据库参数的新信息到来时,你将不可避免地需要更新一些旧信息; 3) 删除元组。 并且以大致相等的概率,有必要从基本关系中删除那些由于收到新信息而不再需要在数据库中存在的元组。 因此,我们概述了修改基本关系的要点。 如何实现这些目标? 在数据库管理系统中,最常见的是内置的基本关系修改运算符。 让我们在伪代码条目中描述它们: 1) 插入运算符 到新元组的基本关系中。 这是运营商 插页. 它看起来像这样: 插入 基本关系名称(属性名称,..) 价值观 (属性值,..); 属性名和属性值后面的元语言符号“,..”告诉我们,该运算符允许多个属性同时添加到基关系中。 在这种情况下,您必须以一致的顺序列出以逗号分隔的属性名称和属性值。 关键词 成 结合运营商的通用名称 插页 表示“插入”并指示括号中的属性要插入的关系。 关键词 价值观 在本声明中, 和 表示分配给这些新声明的属性的“值”、“值”; 2)现在考虑 更新运算符 基础关系中的属性值。 该运算符称为 更新,由英文翻译而来,字面意思是“更新”。 让我们以伪代码表示法给出该运算符的完整一般形式并对其进行解密: 更新 基本关系名称 在 {属性名称 - 属性值},.. 其中 健康)状况; 因此,在关键字之后的运算符的第一行 更新 写入要进行更新的基本关系的名称。 Set关键字由英文翻译为“set”,这行语句指定了要更新的属性的名称和对应的新属性值。 可以在一个语句中一次更新多个属性,这源于使用元语言符号“,..”。 在关键字之后的第三行 其中 编写一个条件,准确显示该基本关系的哪些属性需要更新; 3) 运算符 删除允许 清除 来自基本关系的任何元组。 让我们用伪代码编写它的完整形式并解释所有单个句法单元的含义: 删除自 基本关系名称 其中 健康)状况; 关键词 止 结合运营商的名字 删除 翻译为“删除”。 并且在运算符的第一行中的这些关键字之后,指示基本关系的名称,必须从中删除任何元组。 并且在关键字之后的运算符的第二行 其中 ("where") 表示选择在我们的基本关系中不再需要的元组的条件。 第 9 讲 函数依赖 1. 限制功能依赖 关系的主键和候选键声明所施加的唯一性约束是与概念相关的约束的特例 功能依赖. 要解释函数依赖的概念,请考虑以下示例。 让我们得到一个包含特定会话结果数据的关系。 这种关系的架构如下所示: 会议 (记录簿编号, 全名, 事情, 年级); 属性“Gradebook number”和“Subject”形成该关系的复合主键(因为两个属性被声明为键)。 确实,这两个属性可以唯一确定所有其他属性的值。 但是,除了与此键相关的唯一性约束之外,该关系还必须满足以下条件:一个成绩册发给一个特定的人,因此,在这方面,具有相同成绩册编号的元组必须包含相同的值“姓氏”属性,“名字和中间名”。 如果我们有以下某个教育机构的学生数据库在某个会话之后的片段,那么在成绩簿编号为 100 的元组中,“姓”、“名”和“父名”的属性是相同的,并且属性“主题”和“评估” - 不匹配(这是可以理解的,因为它们谈论的是不同的主题和表现)。 这意味着属性“Last Name”、“First Name”和“Patronymic” 功能依赖 在属性“Gradebook number”上,而属性“Subject”和“Evaluation”在功能上是独立的。 因此, 功能依赖 是数据库管理系统中的单值依赖项。 我们现在给出函数依赖的严格定义。 定义:设 X, Y 是关系 S 方案的子方案,定义方案 S 功能依赖图 X → Y (阅读“X 箭头 Y”)。 让我们定义 函数依赖约束 inv<X → Y> 作为一个声明,关于模式 S,任何两个在投影到子模式 X 上匹配的元组也必须在投影到子模式 Y 上匹配。 让我们以公式的形式写出相同的定义: 库存<X → Y> r(S) = t1,T2 ε r(t1[X] = 吨2[X] ⇒ t1[Y]=t2 [Y]), X, Y ⊆ S; 奇怪的是,这个定义使用了我们之前遇到的一元投影操作的概念。 确实,如果您不使用此操作,还能如何显示关系表的两列而不是行之间的相等性? 因此,我们根据这个操作写到,如果 Y 在功能上取决于十。 有趣的是,在 Y 对 X 的函数依赖的情况下,有人还说 X 功能上定义 Y 或什么 Y 功能依赖 在 X 上。在 X → Y 函数依赖方案中,子电路 X 称为左侧,子电路 Y 称为右侧。 在数据库设计实践中,为了简洁起见,函数依赖模式通常被称为函数依赖。 定义结束。 在特殊情况下,当函数依赖的右侧,即子模式 Y 匹配关系的整个模式时,函数依赖约束成为主键或候选键唯一性约束。 真的: 投资r(S) = ∀ t1,T2 ε r(t1[K] = 吨2 [K] → 吨1(S) = 吨2(S)), K ⊆ S; 只是在定义函数依赖时,需要取键 K 的指定,而不是子方案 X,而不是函数依赖的右侧,子方案 Y,取整个关系方案 S,即实际上,关系键的唯一性限制是限制功能依赖的一个特例,当右侧是整个关系方案中的等值功能依赖方案时。 以下是功能依赖图像的示例: {账簿号码} → {姓,名,姓氏}; {成绩册编号,科目} → {等级}; 2. 阿姆斯壮推理规则 如果任何一个基本关系满足向量定义的函数依赖,那么借助各种特殊的推理规则,就有可能得到这个基本关系一定会满足的其他函数依赖。 这种特殊规则的一个很好的例子是阿姆斯特朗的推理规则。 但在继续分析阿姆斯特朗推理规则本身之前,让我们介绍一个新的元语言符号“├”,称为 可推导元断言符号. 这个符号,在制定规则时,写在两个句法表达式之间,表示它右边的公式是从它左边的公式推导出来的。 现在让我们以以下定理的形式制定阿姆斯特朗推理规则本身。 定理。 以下规则是有效的,称为阿姆斯壮推理规则。 推理规则1。 ├ X → X; 推理规则2。 X→Y├X∪Z→Y; 推理规则3。 X → Y,Y ∪ W → Z ├ X ∪ W → Z; 这里 X、Y、Z、W 是关系 S 模式的任意子模式。可推导元语句符号将前提列表和断言列表(结论)分开。 1.第一条推理规则称为“反身性”,内容如下:“规则推导出来:”X 在功能上蕴含 X“”。这是阿姆斯特朗推导规则中最简单的。它是从字面上推导出来的。 有趣的是,同时具有左右部分的函数依赖被称为 反身的. 根据自反性规则,自反依赖的约束是自动进行的。 2.第二个推理规则称为“补货”,内容如下:“如果 X 在功能上确定 Y,则推导出规则:“子电路 X 和 Z 的并集在功能上包含 Y”。完成规则允许您扩展功能依赖约束的左侧。 3.第三条推理规则称为“伪及物性” 并且读作如下:“如果子电路 X 在功能上需要子电路 Y,并且子电路 Y 和 W 的并在功能上需要 Z,则推导出规则:“子电路 X 和 W 的并在功能上确定子电路 Z”。 伪传递性规则概括了对应于特例 W: = 0 的传递性规则。让我们给出这个规则的正式符号: X→Y,Y→Z ├X→Z。 应该注意的是,前面给出的前提和结论是通过功能依赖方案的名称以缩写形式呈现的。 在扩展形式中,它们对应于以下函数依赖约束。 推理规则1。 投资r(S); 推理规则2。 投资r(S)⇒反函数r(S); 推理规则3。 投资r(S)&inv r(S)⇒反函数r(S); 画 证据 这些推理规则。 1. 规则证明 反身性 当子方案 X 被子电路 Y 替换时,直接来自函数依赖约束的定义。 实际上,采用函数依赖约束: 投资r(S) 并用 X 代替 Y 代入其中,我们得到: 投资r(S),这就是自反性规则。 反身性规则得到证明。 2. 规则证明 补货 让我们用函数依赖图来说明。 第一张图是封装图: 前提:X → Y 第二张图: 结论:X ∪ Z → Y 让元组在 X ∪ Z 上相等。那么它们在 X 上相等。根据前提,它们在 Y 上也相等。 补货规则得到证明。 3. 规则证明 伪及物性 我们还将在图表上进行说明,在这种特殊情况下将是三个。 第一张图是第一个前提: 前提1:X→Y 前提2:Y∪W→Z 最后,第三张图是结论图: 结论:X∪W→Z 让元组在 X ∪ W 上相等。那么它们在 X 和 W 上都相等。根据前提 1,它们在 Y 上也相等。因此,根据前提 2,它们在 Z 上也相等。 证明了伪传递性规则。 所有的规则都被证明了。 3. 推导规则 另一个例子是,如果需要,可以导出新的函数依赖规则,即所谓的 派生推理规则. 这些规则是什么,它们是如何获得的? 众所周知,如果其他规则是通过合法的逻辑方法从一些已经存在的规则推导出来的,那么这些新规则,称为 衍生品, 可以与原始规则一起使用。 需要特别指出的是,这些非常随意的规则正是我们之前经历过的阿姆斯特朗推理规则的“衍生”。 让我们以以下定理的形式制定导出函数依赖关系的导出规则。 定理 以下规则源自阿姆斯壮的推理规则。 推理规则1。 ├ X ∪ Z → X; 推理规则2。 X → Y,X → Z ├ X ∪ Y → Z; 推理规则3。 X → Y ∪ Z ├ X → Y,X → Z; 这里 X、Y、Z、W 与前一种情况一样,是关系 S 方案的任意子方案。 1.第一个派生规则称为 琐碎规则 如下所示: “推导出规则:'子电路 X 和 Z 的并集在功能上必然包含 X'”。 左侧是右侧子集的函数依赖称为 琐碎的. 根据琐碎规则,会自动强制执行琐碎的依赖约束。 有趣的是,琐碎性规则是自反性规则的推广,并且像后者一样,可以直接从函数依赖约束的定义中推导出来。 这条规则的推导并非偶然,与阿姆斯特朗规则体系的完整性有关。 稍后我们将更多地讨论阿姆斯壮规则体系的完整性。 2.第二个派生规则称为 可加性规则 内容如下:“如果子电路 X 在功能上确定子电路 Y,并且 X 同时在功能上确定 Z,则从这些规则推导出以下规则:“X 在功能上确定子电路 Y 和 Z 的并集”。 3.第三个派生规则称为 投射法则 或规则加法反转”。其内容如下:“如果子电路 X 在功能上确定子电路 Y 和 Z 的并集,则从该规则推导出以下规则:“X 在功能上确定子电路 Y,同时 X 在功能上确定子电路Z" ",也就是说,事实上,这个导出的规则是反向可加性规则。 奇怪的是,应用于具有相同左侧部分的函数依赖项的可加性和投影性规则允许一个人组合或相反地拆分依赖项的右侧部分。 在构建推理链时,在制定所有前提之后,应用传递性规则,以便在结论中包含与右侧的函数依赖。 画 证据 列出任意推理规则。 1. 规则证明 琐事. 让我们像所有后续证明一样一步一步地执行它: 1)我们有:X→X(来自阿姆斯特朗的推理自反性规则); 2) 进一步我们有: X ∪ Z → X (通过首先应用 Armstrong 的推理完成规则,然后作为证明的第一步的结果获得)。 琐碎规则已被证明。 2.我们将进行规则的逐步证明 可加性: 1)我们有:X→Y(这是前提1); 2)我们有:X→Z(这是前提2); 3)我们有: Y ∪ Z → Y ∪ Z(来自阿姆斯特朗的推理自反性规则); 4)我们有: X ∪ Z → Y ∪ Z (通过应用阿姆斯特朗推理的伪传递性规则,然后作为证明的第一步和第三步的结果); 5)我们有: X ∪ X → Y ∪ Z (通过应用阿姆斯特朗推理的伪传递性规则获得,然后从第二步和第四步开始); 6)我们有 X → Y ∪ Z(从第五步开始)。 证明了可加性规则。 3。 最后,我们将构建规则的证明 投射性: 1)我们有:X→Y∪Z,X→Y∪Z(这是一个前提); 2)我们有:Y→Y,Z→Z(使用阿姆斯特朗推理的自反性规则得出); 3) 我们有: Y ∪ z → y, Y ∪ z → Z(由阿姆斯壮的推理完成规则和证明第二步的推论得到); 4)我们有:X→Y,X→Z(通过应用阿姆斯特朗推理的伪传递性规则获得,然后作为证明的第一步和第三步的结果)。 投影法则得到证明。 证明了所有的派生推理规则。 4、阿姆斯壮规则体系的完备性 令 F(S) 是在关系方案 S 上定义的给定函数依赖集。 表示为 INV 这组函数依赖所施加的约束。 让我们写下来: 投资r(S) = ∀X → Y ∈F(S) [inv r(S)]。 因此,这组函数依赖施加的限制被破译如下:对于来自函数依赖系统 X → Y 的任何规则,属于函数依赖集 F(S),函数依赖的限制 inv r(S) 在关系集 r(S) 上定义。 让某个关系 r(S) 满足这个约束。 通过将 Armstrong 的推理规则应用于为集合 F(S) 定义的函数依赖关系,我们可以获得新的函数依赖关系,正如我们之前已经说过和证明的那样。 并且,从阿姆斯特朗推理规则的扩展形式可以看出,关系 F(S) 将自动满足这些函数依赖的限制,这是指示性的。 回想一下这些扩展推理规则的一般形式: 推理规则1。 inv < X → X > r(S); 推理规则2。 投资r(S) ⇒ 库存<X ∪ Z → Y> r(S); 推理规则3。 投资r(S) & inv <Y ∪ W → Z> r(S) ⇒ 库存<X ∪ W→Z>; 回到我们的推理,让我们使用 Armstrong 规则用从它派生的新依赖项来补充集合 F(S)。 我们将应用这个补充过程,直到我们不再获得新的功能依赖。 作为这种构造的结果,我们将得到一组新的函数依赖,称为 关闭 设置 F(S) 并表示 F+(S). 确实,这样的名称是很合乎逻辑的,因为我们个人通过长时间的构造,“关闭”了对自身的现有函数依赖集,添加(因此是“+”)所有由现有函数依赖产生的新函数依赖。 应该注意,构造闭包的过程是有限的,因为执行所有这些构造的关系方案本身是有限的。 不用说,闭包是被关闭集合的超集(实际上,它更大!)并且当它再次关闭时不会以任何方式改变。 如果我们把刚才所说的写成公式化的形式,我们会得到: F(S) ⊆ F+(S), [女+(S)]+=F+(S); 进一步,从阿姆斯壮推理规则的被证明的真实性(即合法性、合法性)和闭包的定义来看,任何满足给定函数依赖集约束的关系都将满足属于闭包的依赖约束. X → Y ∈ F+(S) ⇒ ∀r(S) [inv r(S) ⇒ 投资r(S)]; 因此,阿姆斯特朗关于推理规则系统的完备性定理指出,外部蕴涵可以完全合法地被等价所取代。 (我们不会考虑这个定理的证明,因为证明过程本身在我们的特定课程中并不那么重要。) 第 10 讲。范式 一、数据库模式规范化的意义 我们将在本节中考虑的概念与功能依赖的概念有关,即规范化数据库模式的含义与功能依赖系统施加的限制的概念密不可分,并且很大程度上遵循这个概念。 任何数据库设计的起点都是将域表示为一个或多个关系,并且在每个设计步骤中都会生成一组具有“增强”属性的关系模式。 因此,设计过程是一个规范化关系模式的过程,每个连续的范式都具有在某种意义上比前一个更好的属性。 每个范式都有一组特定的约束,如果一个关系满足自己的一组约束,则该关系处于特定的范式。 一个例子是第一范式的限制——关系的所有属性的值都是原子的。 在关系数据库理论中,通常区分以下范式序列: 1)第一范式(1 NF); 2)第二范式(2 NF); 3)第三范式(3 NF); 4)Boyce-Codd范式(BCNF); 5)第四范式(4 NF); 6) 第五范式,或投影-连接范式(5 NF 或 PJ/NF)。 (本课程包括对基本关系的前四种范式的详细讨论,因此我们将不详细分析第四和第五范式。) 范式的主要性质如下: 1) 后面的每个范式在某种意义上都比前面的范式好; 2) 传递到下一个范式时,保留前一个范式的属性。 设计过程是基于归一化的方法,即将一个处于前一个范式的关系分解成两个或多个满足下一个范式要求的关系(当我们自己必须对一个范式进行归一化时,我们会遇到这种情况)当我们阅读材料时)。或其他一些基本关系)。 正如在创建基本关系一节中提到的,给定的函数依赖集对基本关系的模式施加了适当的限制。 这些限制通常通过两种方式实现: 1) 声明式,即通过在基本关系中声明各种类型的主键、候选键和外键(这是使用最广泛的方法); 2)程序上,即编写程序代码(使用上面提到的所谓触发器)。 借助简单的逻辑,您可以理解规范化数据库模式的意义所在。 规范化数据库或将数据库带入规范形式意味着定义这种基本关系方案,以最大限度地减少编写程序代码的需要,提高数据库性能,并促进通过状态和参照完整性维护数据完整性。 也就是说,使代码和使用它对开发人员和用户来说尽可能简单和方便。 为了比较直观地演示非规范化和规范化数据库的操作,请考虑以下示例。 让我们有一个包含有关考试结果的信息的基本关系。 我们之前已经考虑过这样的数据库。 因此, 选项1 数据库模式。 会议 (记录簿编号, 全名, 事情, 年级) 在这个关系中,正如您从基本关系模式图像中看到的那样,定义了一个复合主键: 主键(课本号、学科); 同样在这方面,设置了功能依赖系统: {账簿号码} → {姓,名,姓氏}; 这是具有此关系方案的数据库小片段的表格视图。 我们已经在考虑函数依赖的局限性时使用了这个片段,因此使用它的示例我们将很容易理解这个主题。 这里,为了通过状态来维护数据的完整性,即在改变例如姓氏时,满足功能依赖系统{classbook number}→{Last name,First name,Patronymic}的限制,它是有必要查看这个基本关系的所有元组并依次输入必要的更改。 然而,由于这是一个相当繁琐且耗时的过程(特别是如果我们正在处理大型教育机构的数据库),数据库管理系统的开发人员得出的结论是这个过程需要自动化,即,自动。 现在,可以使用基本关系中各种键的正确声明和所谓的分解(即,将某些东西分解成几个独立的部分)来自动组织对这个(以及任何其他)函数依赖的实现的控制。关系。 因此,让我们将现有的“会话”关系模式划分为两个模式:“学生”模式,其中仅包含有关给定教育机构的学生的信息,以及“会话”模式,其中包含有关上次会话的信息。 然后我们将声明密钥,以便我们可以轻松获得任何必要的信息。 让我们展示一下这些带有键的新关系方案的外观。 选项2 数据库模式。 学生 (记录簿编号, 全名), 主键(成绩册编号)。 会议 (记录簿编号、主题, 年级), 主键(成绩册编号,主题), 外键(成绩册编号)引用学生(成绩册编号)。 我们现在有什么? 对于“Students”,主键“Gradebook number”在功能上决定了其他三个属性:“Last Name”、“First Name”和“Patronymic”。 而关于“Session”,复合主键“Gradebook No.,Subject”也毫不含糊,即字面上功能上定义了该关系方案的最后一个属性——“Score”。 并且这两个关系之间的联系已经建立:通过“Session”关系“Gradebook No”的外键进行,它指的是“Students”关系中的同名属性,当被请求时,提供所有必要的信息。 现在让我们展示与指定相应数据库模式的第二个选项相对应的表所表示的关系的样子。 因此,我们看到,就功能依赖施加的限制而言,规范化的目标是需要使用基础关系的各种类型的主键、候选键和外键的声明,对任何数据库施加所需的功能依赖。 2. 第一范式 (1NF) 在数据库设计和数据库管理方案开发的早期阶段,简单明确的属性被用作最有生产力和最合理的代码单元。 然后他们与简单和复合属性以及单值和多值属性一起使用。 让我们解释每个概念的含义。 复合属性与简单属性相反,是由多个简单属性组成的属性。 多值属性与单值属性不同,是表示多个值的属性。 以下是简单、复合、单值和多值属性的示例。 考虑下表表示关系: 这里的“Phone”属性简单、明确,而“Address”属性简单但多值。 现在考虑另一个具有不同属性的表: 在这种由表表示的关系中,“Phones”属性是简单但多值的,“Addresses”属性既是复合的又是多值的。 通常,简单或复合属性的各种组合是可能的。 在不同的情况下,表示关系的表通常看起来像这样: 在规范化基本关系方案时,程序员可以使用四种最常见的范式之一:第一范式 (1NF)、第二范式 (2NF)、第三范式 (3NF) 或 Boyce-Codd 范式 (NFBC) . 澄清一下:缩写 NF 是英文短语 Normal Form 的缩写。 形式上,除了上述之外,还有其他类型的范式,但以上是最流行的一种。 目前,数据库开发人员正试图避免复合和多值属性,以免编写代码复杂,不使其结构过载,也不会使用户感到困惑。 从这些考虑,第一范式的定义合乎逻辑地遵循。 定义。 任何基本关系都在 第一范式 当且仅当此关系的模式仅包含简单且仅单值的属性,并且必须具有相同的语义。 为了直观地解释规范化和非规范化关系之间的差异,请考虑一个示例。 让,有一个非归一化的关系,具有以下方案。 因此, 选项1 定义了一个简单主键的关系方案: 雇员 (人员编号, 姓氏, 名字, 赞助人, 职位代码, 电话, 录取或解雇日期); 主键(人员编号); 让我们列出这个关系方案中存在哪些错误,即,我们将命名那些使这个方案适当非规范化的符号: 1)“姓氏名字父名”属性是复合的,即由异质元素组成; 2) “Phones”属性是多值的,即它的值是一组值; 3) 属性“接受或解雇日期”没有明确的语义,即在后一种情况下,不清楚输入的日期。 例如,如果引入一个附加属性来更精确地定义日期的含义,那么该属性的值在语义上将是清晰的,但仍然可以只存储每个员工的指定日期之一。 需要做什么才能使这种关系变为正常形式? 首先,有必要将复合属性拆分为简单属性,以排除这些非常复合的属性,以及具有复合语义的属性。 其次,需要对这种关系进行分解,即需要将其分解为几个新的独立关系,以排除多值属性。 因此,考虑到以上所有因素,在将“Employees”关系分解为第一范式或1NF后,我们将得到以下关系的系统,并在其上设置了主键和外键。 因此, 选项2 关系: 雇员 (人员编号, 姓, 名, 赞助人, 职位代码, 录取日期, 解雇日期); 主键(人员编号); 电话 (人员号码、电话); 主键(人员号码、电话); 外键(人员编号)引用Employees(人员编号); 那么我们看到了什么? 复合属性“Surname First Name Patronymic”不再在我们的关系中,取而代之的是“Surname”、“First Name”和“Patronymic”三个简单属性,因此排除了关系“异常”的原因. 此外,我们现在有两个属性“录取日期”和“解雇日期”,而不是语义不明确的属性“雇用或解雇日期”,每个属性都有明确的语义。 因此,我们的“员工”关系不正常的第二个原因也被安全地消除了。 最后,“Employees”关系没有被规范化的最后一个原因是多值属性“Phones”的存在。 要摆脱这个属性,就必须分解整个关系。 由于这种分解,属性“Phones”通常从原始关系“Employees”中排除,但形成了第二个关系——“Phones”,其中有两个属性:“employee's person number”和“Phone” ",即所有属性 - 再次简单,属于第一范式的条件得到满足。 “Employee number”和“Phone”这两个属性构成了“Phones”关系的复合主键,而“Employee number”属性又是一个外键,引用“Employees”中的同名属性”关系,即关系中的“Phones”属性的主键“人员编号”也是外键,指的是“Employees”关系的主键。 因此,在两个关系之间提供了链接。 使用此链接,您可以通过任何员工的人员编号显示其电话的整个列表,而无需花费太多精力和时间,而无需使用复合属性。 请注意,如果与系统存在功能依赖关系,则经过上述所有转换后,规范化将不会完成。 但是,在这个特定示例中,没有函数依赖约束,因此不需要进一步规范化这种关系。 3. 第二范式(2NF) 第二范式或 2NF 对关系提出了更强的要求。 这是因为与第一范式相比,关系的第二范式的定义意味着存在对函数依赖的限制系统。 定义。 基本关系在 第二范式 相对于给定的一组函数依赖当且仅当它是第一范式,此外,每个非键属性在功能上完全依赖于每个键。 在这个定义中 非关键属性 是不包含在关系的任何主键或候选键中的任何关系属性。 对密钥的完全功能依赖意味着对该密钥的任何部分都没有功能依赖。 因此,现在,在对关系进行规范化时,我们还必须监控关系处于第一范式的条件是否满足,即确保其属性简单且明确,以及关于关系的第二个条件是否满足函数依赖的限制。 很明显,与简单键(主键和候选键)的关系肯定是第二范式。 实际上,在这种情况下,似乎根本不可能依赖密钥的一部分,因为密钥根本没有任何单独的部分。 现在,就像在上一个主题的段落中一样,考虑一个非规范化关系方案和规范化过程本身的示例。 因此, 选项1 关系方案: 观众(大楼号、礼堂号, 面积平方。 米,军团的第一个服务指挥官); 主键(语料库号、受众号); 此外,还定义了以下功能依赖系统: {军团编号}→{军团服役指挥官编号}; 我们看到了什么? 这个关系“观众”保持第一范式的所有条件都满足了,因为这个关系的每一个属性都是明确和简单的。 但不满足每个非关键元素必须在功能上完全依赖于关键的条件。 为什么? 是的,因为“军团参谋长号”这个属性在功能上不依赖于“军团号,观众号”这个复合键,而是依赖于这个键的一部分,即属性“军团号”。 确实,毕竟是军团编号完全决定了分配给它的特定指挥官,而军团指挥官的人员编号又不能取决于任何礼堂编号。 因此,我们规范化的主要任务变成了确保密钥以这样一种方式分布的任务,特别是属性“No. 为了实现这一点,我们将不得不再次应用关系的分解,就像上一段一样。 所以,下面的关系系统,即 选项2 “Audience”关系只是从原来的关系中分解成几个新的独立关系得到的: 军团(案例编号,军团的人事指挥官编号); 主键(案例号); 观众(大楼号、礼堂号, 面积平方。 米); 主键(语料库号、受众号); 外键(案例号)引用案例(案例号); 我们现在看到了什么? 关于“Corpus”的非关键属性“军团指挥官的人员编号”在功能上完全依赖于主键“军团编号”。 这里完全满足求出第二范式关系的条件。 现在让我们继续考虑第二个关系——“观众”。 对于“Audience”,主键属性“Case#”也是外键,指的是“Case”关系的主键。 在这方面,非键属性“面积平方米”完全依赖于整个复合主键“建筑物#,礼堂#”,不依赖,甚至不能依赖它的任何部分。 因此,通过分解原来的关系,我们得出结论,第二范式定义中的所有条件都完全满足。 在这个例子中,所有的功能依赖要求都是由主键(这里没有候选键)和外键的声明强加的。 因此,不需要进一步的标准化。 4. 第三范式(3NF) 我们将看到的下一个范式是第三范式(或 3NF)。 与第一个范式以及第二个范式不同,第三个范式意味着将函数依赖系统与关系一起分配。 让我们制定一个关系必须具有哪些属性才能将其简化为第三范式。 定义。 基本关系在 第三范式 关于给定的一组函数依赖当且仅当它是第二范式并且每个非键属性在功能上完全依赖于键。 因此,第三范式的要求比第一范式和第二范式的要求强,甚至结合起来。 事实上,在第三范式中,每个非键属性都依赖于键,并且依赖于整个键,除了键之外什么都不依赖。 让我们说明将非规范化关系带入第三范式的过程。 为此,请考虑一个示例:不是第三范式的关系。 因此, 选项1 关系“雇员”的计划: 雇员 (人员编号, 姓, 名, 赞助人, 职位代码, 薪水); 主键(人员编号); 另外,在这个“Employees”关系之上设置了如下的函数依赖系统: {职位代码} → {工资}; 事实上,作为一项规则,工资金额,即工资金额,直接取决于职位,因此取决于相应数据库中的代码。 这就是为什么这种关系“Employees”不是第三范式的原因,因为事实证明,非关键属性“Salary”在功能上完全依赖于属性“Position code”,尽管该属性不是关键属性。 奇怪的是,任何关系都可以简化为第三范式,其方式与此之前的两种形式完全相同,即通过分解。 分解“Employees”关系后,我们得到以下新的独立关系系统: 因此, 选项2 关系“雇员”的计划: 职位(职位代码, 薪水); 主键(位置代码); 雇员 (人员编号, 姓, 名, 赞助人, 职位代码); 主键(位置代码); 外键(职位代码)引用职位(职位代码); 现在,正如我们所见,关于“职位”,非关键属性“薪水”在功能上完全依赖于简单的主键“职位代码”,并且仅依赖于该键。 请注意,关于“员工”,所有四个非关键属性“姓氏”、“名字”、“Patronymic”和“职位代码”在功能上完全依赖于简单的主键“Employment Number”。 在这方面,“Position ID”属性是一个外键,它引用“Positions”关系的主键。 在此示例中,所有要求都是通过声明简单的主键和外键来施加的,因此不需要进一步的规范化。 知道在实践中通常将自己限制为将数据库带入第三范式是有趣且有用的。 同时,关键属性对同一关系的其他属性的某些功能依赖可能不会被强加。 使用前面提到的触发器(即在程序上,通过编写适当的程序代码)来实现对此类非标准功能依赖项的支持。 此外,触发器必须使用这种关系的元组进行操作。 5. Boyce-Codd 范式 (NFBC) Boyce-Codd 范式紧随第三范式之后的“复杂性”。 因此,Boyce-Codd 范式有时也简称为 强第三范式 (或加强 3 NF)。 她为什么要加强? 我们制定了 Boyce-Codd 范式的定义: 定义。 基本关系在 博伊斯范式 - 科德 当且仅当它是第三范式,并且不仅任何非键属性在功能上完全依赖于任何键,而且任何键属性必须在功能上完全依赖于任何键。 因此,非键属性实际上依赖于整个键并且只依赖于键的要求也适用于键属性。 在 Boyce-Codd 范式的关系中,关系中的所有函数依赖都由键的声明强加。 但是,当将数据库关系简化为 Boyce-Codd 形式时,可能会出现各种关系的属性之间的依赖关系不是强加的函数依赖关系的情况。 当触发器对单个关系的元组进行操作时,使用对不同关系的元组操作的触发器来支持这种函数依赖比在第三范式的情况下更困难。 除此之外,设计数据库管理系统的实践表明,将基本关系带入 Boyce-Codd 范式并不总是可能的。 注意到异常的原因是第二范式和第三范式的要求不需要对作为其他可能键的组件的属性的主键的最小功能依赖性。 这个问题由范式解决,该范式在历史上称为 Boyce-Codd 范式,是在存在多个重叠可能键的情况下对第三范式的改进。 一般来说,数据库模式规范化使数据库更新更有效地执行数据库管理系统,因为它减少了维护数据库完整性的检查和备份的数量。 在设计关系数据库时,您几乎总是会实现数据库中所有关系的第二范式。 在频繁更新的数据库中,它们通常会尝试提供关系的第三种范式。 Boyce-Codd 范式得到的关注要少得多,因为在实践中,关系具有多个复合重叠候选键的情况很少见。 以上这些都使得 Boyce-Codd 范式在开发程序代码时使用起来不太方便,因此,如前所述,在实践中,开发人员通常将自己的数据库限制为第三范式。 然而,它也有自己相当奇怪的特点。 关键是关系是第三范式但不是 Boyce-Codd 范式的情况在实践中极为罕见,即在简化为第三范式后,通常所有函数依赖都由主要、候选和外键,因此不需要触发器来支持功能依赖。 但是,仍然需要触发器来支持不通过功能依赖关系链接的完整性约束。 6.范式的嵌套 范式嵌套是什么意思? 范式的嵌套 - 这是弱化和强化形式的概念相对于彼此的比率。 范式的嵌套完全遵循它们各自的定义。 让我们想象一个图表来说明我们已知的范式的嵌套关系: 让我们通过具体的例子来解释弱化和强化范式的概念。 第一个范式相对于第二个范式(以及所有其他范式)被削弱了。 的确,回顾我们经历过的所有范式的定义,我们可以看到每个范式的要求都包括属于第一个范式的要求(毕竟,它被包含在每个后续定义中)。 第二范式强于第一范式,但弱于第三范式和 Boyce-Codd 范式。 事实上,属于第二范式的定义包含在第三范式的定义中,而第二范式本身又包含第一范式。 Boyce-Codd 范式不仅相对于第三范式得到加强,而且相对于它之前的所有其他范式也得到加强。 反过来,第三范式仅相对于 Boyce-Codd 范式被削弱。 第 11 讲。设计数据库模式 在逻辑级别进行设计时,最常用的抽象数据库模式的方法是所谓的 实体关系模型. 它有时也被称为 ER模型,其中ER是英文短语Entity-Relationship的缩写,字面意思是“实体-关系”。 这种模型的元素是实体类、它们的属性和关系。 我们将对这些元素中的每一个进行解释和定义。 实体类 就像面向对象编程意义上的无方法对象类。 当移动到物理层时,实体类被转换为特定数据库管理系统的基本关系数据库关系。 它们和基本关系本身一样,也有自己的属性。 让我们对刚刚给出的对象给出一个更精确和严格的定义。 班级 被称为具有共同属性、操作、关系和语义的对象集合的命名描述。 在图形上,一个类通常被描述为一个矩形。 每个类都必须有一个名称(文本字符串),以将其与所有其他类唯一区分开来。 类属性 是一个类的命名属性,描述了该属性的实例可以采用的一组值。 一个类可以有任意数量的属性(特别是,它可以没有属性)。 由属性表示的属性是给定类的所有对象共有的建模实体的属性。 所以属性是对象状态的抽象。 任何类对象的任何属性都必须具有某些值。 所谓的关系是通过声明外键来实现的(我们之前已经遇到过类似的现象),即在关系中,声明的外键是指一些其他关系的主键或候选键。 通过这个,几个不同的独立基本关系被“链接”到一个称为数据库的单一系统中。 此外,使用统一建模语言 UML 描述了构成实体关系模型的图形基础的图。 许多书籍专门介绍面向对象的建模语言 UML(或统一建模语言),其中许多已被翻译成俄语(还有一些由俄语作者撰写)。 一般来说,UML 允许您对不同类型的系统进行建模:纯软件、纯硬件、软件-硬件、混合、明确包括人类活动等。 但是,正如我们已经提到的,UML 语言被积极地用于设计关系数据库。 为此,使用了语言的一小部分(类图),甚至没有全部使用。 从关系数据库设计的角度来看,建模功能与 ER 图并没有太大区别。 我们还想表明,在关系数据库设计的上下文中,基于使用 ER 图的结构设计方法和基于使用 UML 语言的面向对象方法主要仅在术语上有所不同。 ER 模型在概念上比 UML 更简单,它的概念、术语和应用程序选项更少。 这是可以理解的,因为不同版本的 ER 模型是专门为支持关系数据库设计而开发的,而 ER 模型几乎不包含超出关系数据库设计人员实际需求的功能。 UML 属于对象世界。 这个世界比关系世界复杂得多(如果你愿意,更难以理解,更混乱)。 因为 UML 可用于对任何事物进行统一的面向对象建模,所以该语言包含大量从关系数据库设计角度来看是多余的概念、术语和用例。 如果我们从类图的一般机制中提取关系数据库设计真正需要的东西,那么我们将得到完全不同的符号和术语的 ER 图。 奇怪的是,在 UML 中形成类名时,允许任意组合字母、数字甚至标点符号。 但是,在实践中,建议使用简短而有意义的形容词和名词作为类名,每个类名都以大写字母开头。 (我们将在讲座的下一段中更详细地考虑图表的概念。) 1. 债券种类繁多 数据库模式设计中的关系之间的关系被描述为连接实体类的线。 此外,连接的每一端都可以(并且通常应该)由名称(即连接的类型)和连接中类角色的多样性来表征。 让我们更详细地考虑多重性和连接类型的概念。 多样性 (多重性)是一个特征,它指示具有给定角色的实体类的多少属性可以或应该参与某种关系的每个实例。 设置关系角色基数的最常用方法是直接指定特定的数字或范围。 例如,指定“1”表示具有给定角色的每个类都必须参与该连接的某个实例,并且具有该角色的类的一个对象可以参与该连接的每个实例。 指定范围“0..1”表示并非具有给定角色的类的所有对象都需要参与该关系的任何实例,而只有一个对象可以参与该关系的每个实例。 让我们更详细地讨论多重性。 数据库设计系统中典型的、最常见的基数是以下基数: 1) 1 - 对应端的连接重数等于一; 2) 0...1 - 这种表示形式意味着给定连接在其对应端的重数不能超过 XNUMX; 3) 0... ∞ - 这种多重性可以简单地解读为“许多”。 奇怪的是,通常来说,“很多”意味着“没什么”。 4) 1... ∞ - 此指定用于表示“一个或多个”的多重性。 让我们举一个简单图表的例子来说明不同多重链接的工作。 根据这张图,可以很容易地理解每个售票处都有很多票,而每张票又位于一个(且仅此而已)售票处。 现在考虑最常见的链接类型或名称。 让我们列出它们: 1) 1:1 - 这个名称是给连接“一对一",也就是说,它可以说是两个集合的一一对应; 2) 1 : 0... ∞ - 这是一个连接的名称,如“一对多”。为简洁起见,这种关系称为“1:M”。在前面考虑的图表中,如您所见,只有这样一个名称的关系; 3) 0... ∞ : 1 - 这是先前连接的反转或类型为“的连接”多对一"; 4) 0... ∞ : 0... ∞ 是一个连接的名称,如“多对多",即链接的每一端都有许多属性; 5) 0... 1 : 0... 1 - 这是一个类似于之前介绍的“一对一”类型连接的连接,它又被称为“不超过一到不超过一"; 6) 0... 1 : 0... ∞ - 这是类似于一对多连接的连接,称为“不超过一对多”; 7) 0... ∞ : 0... 1 - 这是一个连接,反过来,类似于多对一类型的连接,它被称为“许多到不超过一个". 如您所见,最后三个连接是从我们讲座中在数字一、二和三下列出的连接中获得的,方法是将“一”的多重性替换为“不超过一个”的多重性。 2. 图表。 图表类型 现在让我们最终直接考虑图表及其类型。 一般来说,逻辑模型分为三个层次。 这些级别在有关数据结构的信息的表示深度上有所不同。 这些级别对应于下图: 1) 演示图; 2) 关键图; 3) 完整的属性图。 让我们分析每种类型的图表,并详细解释它们在数据结构信息呈现深度方面的差异的含义。 1. 演示图. 这样的图只描述了最基本的实体类及其关系。 此类图中的键可能根本没有描述,因此,连接可能不会以任何方式个性化。 因此,多对多关系是可以接受的,尽管它们通常被避免,或者,如果它们确实存在,则进行微调。 复合属性和多值属性也是完全有效的,尽管我们之前写过,与这些属性的基本关系不会被简化为任何范式。 有趣的是,在我们考虑的三种类型的图表中,只有最后一种类型(完整的属性图)假设与它一起呈现的数据是某种正常形式。 而已经考虑过的演示图和紧随其后的关键图并不意味着任何类型的东西。 这种图表通常用于演示(因此它们的名称 - 演示,即用于演示、演示,不需要过多的细节)。 有时在设计数据库时,有必要咨询该特定数据库处理信息的主题领域的专家。 然后还使用演示图,因为为了从远离编程的专业的专家那里获得必要的信息,根本不需要过度澄清具体细节。 2. 按键图. 与表示图不同,键图必须描述所有实体类及其关系,然而,仅根据主键。 在这里,多对多关系已经很详细了(即,这种类型的纯粹形式的关系根本无法在此处指定)。 多值属性仍然允许以与表示图中相同的方式,但如果它们出现在关键图中,它们通常会转换为独立的实体类。 但是,奇怪的是,明确的属性仍然可以不完全地表示或描述为复合的。 这些“自由”在表示图和关键图等图表中仍然有效,但在下一种图表中是不允许的,因为它们确定基本关系未规范化。 因此,我们可以得出结论,未来的关键图只假设已经描述的实体类上的“悬挂”属性,即使用表示图,描述最必要的实体类就足够了,然后使用关键图添加所有内容为其必要的属性并指定所有最重要的链接。 3. 全属性图. 全属性图最详细地描述了上述所有实体类、它们的属性以及这些实体类之间的关系。 通常,此类图表代表第三范式的数据,因此在此类图表描述的基本关系中,自然不允许复合或多值属性,就像不存在非粒度多对-许多关系。 但是,完整的属性图还有一个缺点,那就是在数据表现方面不能完全称得上是最完整的图表。 例如,在使用全属性图时,特定数据库管理系统的特殊性仍然没有被考虑在内,特别是,数据类型仅在所需的建模逻辑级别所必需的范围内指定。 3. 关联和密钥迁移 早些时候,我们已经讨论过数据库中的关系。 特别是,关系是在声明关系的外键时建立的。 但是在我们课程的这一部分中,我们不再讨论基本关系,而是讨论实体的收银机。 从这个意义上说,建立关系的过程还是和各种key的声明相关联的,但是现在我们讲的是实体类的key。 即,建立关系的过程与将一个实体类的简单或复合主键转移到另一个类相关联。 这种转移的过程也称为 密钥迁移. 在这种情况下,主键被转移的实体类被称为 父类, 外键迁移到的实体类称为 儿童班 实体。 在子实体类中,键属性接受外键属性的状态,可能参与也可能不参与自己主键的形成。 因此,当主键从父实体类迁移到子实体类时,子类中会出现一个引用父类主键的外键。 为了方便键迁移的公式表示,我们引入以下键标记: 1) PK - 这就是我们将如何表示主键(主键)的任何属性; 2) FK - 用这个标记我们将表示外键(外键)的属性; 3) PFK - 使用这样的标记,我们将表示主/外键的属性,即任何此类属性是某个实体类的唯一主键的一部分,同时也是同一实体类的某个外键的一部分. 因此,具有 PK 和 FK 标记的实体类的属性构成了该类的主键。 和带有 FK 标记的属性和 PFK 是这个实体类的一些外键的一部分。 通常,密钥可以以不同的方式迁移,并且在每种不同的情况下,都会出现某种连接。 因此,让我们考虑根据密钥迁移方案有哪些类型的链接。 总共有两种密钥迁移方案。 1. 迁移方案 ∀PK(PK |→PFK); 本条目中,符号“|→”表示“迁移”的概念,即上式将读作:将父实体类的主键PK的任意(each)属性迁移(迁移)到首要的关键 PFK 子实体类,当然,它也是该类的外键。 在这种情况下,我们说的是,无一例外,父实体类的每一个关键属性都必须迁移到子实体类中。 这种类型的连接称为 识别,因为父实体类的键完全参与子实体的识别。 在标识类型的链接中,依次有两种可能的独立类型的链接。 因此,有两种类型的识别链接: 1) 完全识别. 当且仅当父实体类的迁移主键的属性完全形成子实体类的主(和外)键时,才称标识关系是完全标识的。 完全识别关系有时也称为 明确的,因为完全识别关系识别所有类别的子实体; 2) 不完全识别. 当且仅当父实体类的迁移主键的属性仅部分构成子实体类的主键(同时是外键)时,标识关系才称为不完全标识。 因此,除了带有标记的键 PFK 也将有一个标记为 PK 的键。 在这种情况下,子实体类的外键PFK将完全由父实体类的主键PK决定,而单纯的这个子关系的主键PK将不会由父实体的主键PK决定实体类,它将独立存在。 二、迁移方案 ∃PK(PK |→ FK); 这样的迁移方案应该理解为:父实体类有这样的主键属性,在迁移过程中,转移到子实体类的强制非键属性。 因此,在这种情况下,我们谈论的事实是,与前一种情况一样,父实体类的一些主键属性被转移到子实体类,而不是全部。 另外,如果之前的迁移方案定义了迁移到子关系的主键,同时也变成了外键,那么最后的类型迁移决定了父实体类的主键属性迁移到普通,最初是非键属性,之后获得外键状态。 这种类型的连接称为 非识别,因为实际上父键并不完全参与子实体的形成,它根本不识别它们。 在非识别关系中,还区分了两种可能的关系类型。 因此,非识别关系有以下两种类型: 1) 必然是非识别性的. 当且仅当禁止子实体类的所有迁移键属性的 Null 值时,非标识关系才被称为必然非标识; 2) 可选地非识别性. 当且仅当子实体类的一些迁移键属性允许空值时,才说非标识关系不一定是非标识的。 我们以下表的形式总结了上述所有内容,以便于系统化和理解所提供材料的任务。 同样在此表中,我们将包含有关哪种类型的关系(“不超过一对一”、“多对一”、“多对不超过一个”)对应于哪种类型的关系(完全识别,不完全识别,不一定是识别,不一定是非识别)。 所以,父子实体类之间,根据关系的类型,建立了如下类型的关系。 因此,我们看到在除最后一种情况外的所有情况下,引用都不为空(not null)→ 1。 请注意,在除最后一种情况外的所有情况下,在连接的父端,多重性都设置为“一”。 这是因为在这些关系的情况下(即完全标识、不完全标识和不一定标识类型的关系)外键的值必须对应(并且,而且,唯一)主键的值父实体类。 而在后一种情况下,由于外键的值可以等于Null值(FK:空有效性标志),因此在父端将重数设置为“不超过一个”关系。 我们进一步分析。 在连接的子端,除第一种情况外,在所有情况下,多重性都设置为“许多”。 这是因为,由于不完全识别,如第二种情况,(或者根本没有这种识别,在第二种情况和第三种情况下),父实体类的主键的值可以在值之间重复出现子类的外键。 而第一种情况,关系是完全标识的,所以父实体类的主键属性在子实体类的键属性中只能出现一次。 第12讲 实体类的关系 因此,我们已经了解的所有概念,即图表及其类型、关系的多样性和类型,以及密钥迁移的类型,现在将帮助我们了解有关相同关系的材料,但已经在特定类之间实体。 其中,正如我们将要看到的,也有各种各样的联系。 1.层次递归关系 我们将考虑的实体类之间的第一种关系是所谓的 层次递归关系. 根本 递归 ( 递归链接) 是实体类与其自身的关系。 有时,类比生活情境,这样的联系也被称为“鱼钩”。 层次递归关系 (或简单地说 层次递归) 是“最多一对多”类型的任何递归关系。 分层递归最常用于以树结构存储数据。 在指定分层递归关系时,必须将父实体类(在这种特定情况下也充当子实体类)的主键作为外键迁移到同一实体类的强制非键属性。 所有这些对于保持“分层递归”概念的逻辑完整性都是必要的。 因此,考虑到以上所有内容,我们可以得出结论,层次递归关系只能是 不一定非识别 没有其他的,因为如果使用任何其他类型的关系,外键的 Null 值将无效并且递归将是无限的。 同样重要的是要记住,属性不能在同一个实体类中以相同的名称出现两次。 因此,必须为迁移的键的属性赋予所谓的角色名称。 因此,在分层递归关系中,节点的属性使用外键进行扩展,该外键是对其直接祖先节点的主键的可选引用。 让我们构建一个在关系数据模型中实现层次递归的表示和关键图,并给出一个表格形式的例子。 让我们先创建一个演示图: 现在让我们构建一个更详细的关键图: 考虑一个例子,它清楚地说明了这种关系类型,如层次递归关系。 让我们给出以下实体类,它与前面的示例一样,由“Ancestor Code”和“Node Code”属性组成。 首先,让我们展示这个实体类的表格表示: 现在让我们构建一个表示此类实体的图表。 为此,我们从表中选择所有必要的信息:代码为“一”的节点的祖先不存在或未定义,由此我们得出结论,节点“一”是一个顶点。 同一节点“一”是代码为“二”和“三”的节点的祖先。 反过来,代码为“二”的节点有两个孩子:代码为“四”的节点和代码为“五”的节点。 而代码为“三”的节点只有一个子节点——代码为“六”的节点。 因此,考虑到以上所有内容,让我们构建一个树结构来反映有关上表中包含的数据的信息: 所以,我们已经看到使用层次递归关系来表示树结构真的很方便。 2.网络递归通信 实体类之间的网络递归连接,可以说是我们已经通过的层次递归连接的多维模拟。 只有当层次递归被定义为“最多一对多”的递归关系时,那么 网络递归 表示相同的递归关系,只是“多对多”类型。 由于许多类别的实体在每一侧都参与此连接,因此称为网络连接。 正如您已经可以通过类比层次递归猜到的那样,网络递归类型的链接旨在表示图形数据结构(而层次链接的使用,我们记得,专门用于树结构的实现)。 但是,由于在网络递归类型的连接中指定了“多对多”类型的连接,因此不可能不对其进行额外的详细说明。 因此,为了细化模式中的所有多对多关系,有必要创建一个新的独立实体类,其中包含对 Ancestor-Descendant 关系的父或后代的所有引用。 这样的类一般称为 关联实体类. 在我们的特殊情况下(在我们课程中要考虑的数据库中),关联实体没有自己的附加属性,因此称为 呼唤,因为它通过引用来命名祖先-后代关系。 因此,表示主机的实体类的主键必须两次迁移到关联实体类。 在这个类中,迁移的键一起必须形成一个复合主键。 综上所述,我们可以得出结论,在使用网络递归时建立链接不应该是完全识别而已。 就像使用层次递归关系时一样,使用网络递归作为关系时,任何属性都不能在同一个实体类中以相同的名称出现两次。 所以和上次一样,特别规定迁移key的所有属性都必须接受角色名。 为了说明网络递归通信的操作,让我们构建一个在关系数据模型中实现网络递归的演示文稿和关键图。 让我们从演示图开始: 现在让我们构建一个更详细的键图: 我们在这里看到什么? 我们看到这个关键图中的两个连接都是“多对一”连接。 而且,重数“0...∞”或重数“多”位于面向实体的命名类的连接的末端。 确实,有很多链接,但它们都引用一个节点代码,这是“Nodes”实体类的主键。 最后,让我们考虑一个示例,说明实体类对这种连接类型的操作作为网络递归。 让我们给出一些实体类的表格表示,以及包含有关链接信息的命名实体类。 让我们来看看这些表。 结: 参考文献: 事实上,上面的表示是详尽无遗的:它提供了所有必要的信息,以便轻松地重现此处编码的图结构。 例如,我们可以毫无障碍地看到代码为“一”的节点有三个孩子,代码分别为“二”、“三”和“四”。 我们还看到代码为“二”和“三”的节点根本没有后代,代码为“四”的节点(以及节点“一”)有三个后代,代码为“一”、“二”和三”。 让我们绘制一个由上面给出的实体类给出的图: 因此,我们刚刚构建的图是使用网络递归类型连接链接实体类的数据。 3.协会 在我们特定课程的考虑中包括的所有类型的连接中,只有两种是递归连接。 我们已经设法考虑了它们,它们分别是分层和网络递归链接。 我们必须考虑的所有其他类型的关系都不是递归的,但通常表示几个父实体类和几个子实体类的关系。 此外,正如您可能猜到的那样,父实体类和子实体类现在永远不会重合(实际上,我们不再谈论递归)。 本节讲到的连接称为关联,准确指的是非递归类型的连接。 所以连接称为 协会, 被实现为多个父实体类和一个子实体类之间的关系。 同时,奇怪的是,这种关系是由各种类型的关系来描述的。 还值得注意的是,在关联过程中只能有一个父实体类,就像在网络递归中一样,但即使在这种情况下,来自子实体类的关系也必须至少有两个。 有趣的是,在关联以及网络递归中,存在特殊类型的实体类。 这种类的一个例子是子实体类。 确实,在一般情况下,在一个关联中,一个子实体类被称为 关联实体类. 在关联实体类没有自己的附加属性并且仅包含与父实体类的主键一起迁移的属性的特殊情况下,这样的类称为 命名实体类. 如您所见,这与网络递归连接中的关联和命名实体的概念几乎是绝对类比的。 大多数情况下,关联用于细化(解决)多对多关系。 让我们来说明这个说法。 举个例子,给我们下面的演示图,它描述了某医院接待某位医生的方案: 这个图的字面意思就是医院里有很多医生和很多病人,医生和病人之间没有其他的关系和对应关系。 因此,当然,有了这样一个数据库,医院管理部门永远不会清楚如何为不同的病人安排不同医生的预约。 很明显,这里使用的多对多关系只需要详细说明,以便具体化各种医生和患者之间的关系,换句话说,合理地组织所有医生和他们的患者的约会时间表医院。 现在让我们构建一个更详细的键图,其中我们已经详细说明了所有现有的多对多关系。 为此,我们将相应地引入一个新的实体类,我们将其称为“Receive”,它将充当关联实体类(稍后我们将看到为什么这将是一个关联实体类,而不仅仅是一个命名类实体,我们之前讨论过)。 所以我们的关键图将如下所示: 所以,现在你可以清楚地看到为什么新类“Receiving”不是一个命名实体类。 毕竟这个类有自己的附加属性“Date-Time”,因此,根据定义,新引入的类“Reception”是一个关联实体类。 这个类通过执行这个或那个约会的时间将“医生”和“病人”实体类相互“关联”起来,这使得使用这样的数据库更加方便。 因此,通过引入“日期-时间”属性,我们从字面上组织了各种医生急需的工作时间表。 我们还看到“Reception”实体类的外部主键“Doctor's Code”引用了“Doctors”实体类的同名主键。 同样,“Reception”实体类的外部主键“Patient Code”引用了“Patient”实体类中的同名主键。 在这种情况下,理所当然地,实体类“医生”和“病人”是父类,而关联实体类“接待处”又是唯一的子类。 我们可以看到,之前演示图中的多对多关系现在已经完全详细了。 我们在上面的演示图中看到的不是一个多对多关系,而是两个多对一关系。 第一个关系的子端有多重性“many”,字面意思是“Reception”实体类有很多医生(他们都在医院)。 而在这个关系的父端是“一”的多重性,这是什么意思呢? 这意味着在“Reception”实体类中,每个特定医生的每个可用代码都可以无限多次出现。 事实上,在医院的时间表中,同一位医生的代码在不同的日期和时间出现了很多次。 这是相同的代码,但已经在“医生”实体类中,它只能出现一次。 事实上,在所有医院医生的列表中(“医生”实体类就是这样一个列表),每个特定医生的代码只能出现一次。 类似的事情发生在父类“Patient”和子类“Patient”之间的关系上。 在所有医院患者的列表中(在“患者”实体类中),每个特定患者的代码只能出现一次。 但另一方面,在预约时间表中(在实体类“接待处”中),特定患者的每个代码可以任意多次出现。 这就是键末端的多重性以这种方式排列的原因。 作为在关系数据模型中实现关联的示例,让我们构建一个模型来描述客户和承包商之间的会议安排,顾问可以选择参与。 我们不会详细介绍演示图,因为我们需要全面考虑图表的构建,而演示图无法提供这样的机会。 因此,让我们构建一个关键图来反映客户、承包商和顾问之间关系的本质。 那么,下面开始对上面的关键图进行详细的分析。 首先,“Graph”类是关联实体类,但是,如前例所示,它不是命名实体类,因为它有一个属性不会随键迁移到其中,而是它的自己的属性。 这是“日期-时间”属性。 其次,我们看到子实体类“Chart”“Customer code”“Executor code”“Date-Time”的属性构成了这个实体类的复合主键。 “顾问代码”属性只是“图表”实体类的外键。 请注意,此属性允许在其值中使用 Null 值,因为根据条件,不需要顾问出席会议。 此外,第三,我们注意到(三个可用链接中的)前两个链接没有完全识别。 即,不完全识别,因为两种情况下的迁移键(主键“Customer code”和“Executor code”)都没有完全形成“Graph”实体类的主键。 事实上,“日期 - 时间”属性仍然存在,它也是复合主键的一部分。 在这两个不完全识别的键的末端,标记了多重性“一”和“许多”。 这样做是为了显示(如关于医生和患者的示例)在不同实体类中提及客户代码或执行者代码之间的区别。 实际上,在“Graph”实体类中,任何客户或承包商代码都可以根据需要出现多次。 因此,在这一点,孩子,连接的末端有“许多”的多样性。 而在“Customers”或“Contractors”实体类中,customer或contractor的每一个代码分别只能出现一次且只能出现一次,因为这些实体类中的每一个无非就是所有客户和表演者的完整列表。 因此,在连接的父端,存在多个“一”。 最后,请注意第三种关系,即“Graph”实体类与“Consultants”实体类的关系,不一定是非标识性的。 确实,在这种情况下,我们说的是将“顾问”实体类的关键属性“顾问代码”传递给同名的“图形”实体类的非关键属性,即主键“Graph”实体类中的“Consultants”实体类未识别此类的主键。 而且前面说了“Advisor Code”属性是允许Null值的,所以这里恰恰是使用了非标识关系。 因此,“顾问代码”属性获取外键的状态,仅此而已。 我们还要注意放置在这个不完全非识别链接的父端和子端的链接的多样性。 它的父端有一个“不超过一个”的重数。 事实上,如果我们回想一下不是完全非标识的关系的定义,那么我们就会明白,“Graph”实体类中的“Consultant code”属性不能对应于所有顾问列表中的多个顾问代码(这是“顾问”实体类)。 通常,它可能不会对应于任何顾问代码(记住空值可接受性复选框 顾问代码:空),因为根据条件,顾问在一般来说,客户和承包商之间的会议是没有必要的。 4.概括 我们将考虑的实体类之间的另一种关系是以下形式的关系 概括. 它也是一种非递归关系。 所以,像这样的关系 概括 被实现为一个父实体类与多个子实体类的关系(与之前的 Association 关系相反,后者处理多个父实体类和一个子实体类)。 在使用泛化关系制定数据表示规则时,必须马上说,这种一个父实体类和几个子实体类的关系是通过完全标识关系来描述的,即分类关系。 回顾完全标识关系的定义,我们得出结论,在使用Generalization时,父实体类主键的每个属性都传递给子实体类的主键,即父实体类的主迁移键的属性实体类完全形成所有子实体类的主键,它们标识它们。 奇怪的是,泛化实现了所谓的 类别层次 或继承层次结构。 在这种情况下,父实体类定义 通用实体类,以所有子类的实体或所谓的实体共有的属性为特征 分类实体 即,父实体类是其所有子实体类的字面概括。 作为在关系数据模型中实现泛化的示例,我们将构建以下模型。 该模型将基于“学生”的广义概念,并将描述以下分类概念(即,它将概括以下子实体类):“学童”、“学生”和“研究生”。 因此,让我们构建一个关键图来反映父实体类和子实体类之间关系的本质,通过泛化类型的连接来描述。 那么我们看到了什么? 首先,“Schoolchildren”、“Students”、“Postgraduate students”这些基本关系(或者来自实体类,是一样的)分别对应自己的属性,如“Class”、“Course”、“Year of study” “。 这些属性中的每一个都表征其自己的实体类的成员。 我们还看到父实体类“Students”的主键迁移到每个子实体类并在那里形成主外键。 在这些联系的帮助下,我们可以通过任何学生的代码确定他的名字、姓氏和父名,这些信息我们在相应的子实体类本身中找不到。 其次,由于我们谈论的是实体类的完全识别(或分类)关系,因此我们将注意父实体类与其子类之间关系的多样性。 这些链接中每一个的父端都具有“一”的重数,并且链接的每个子端具有“至多一”的重数。 如果我们回想一下实体类完全标识关系的定义,就会清楚真正唯一的学生代码,即“学生”实体类的主键,在每个子实体中最多指定一个具有此类代码的属性“学生”、“学生”和“研究生”类。 因此,所有债券都具有这样的多重性。 让我们编写一个操作符片段,用于创建基本关系“Schoolchildren”和“Students”,并定义维护级联类型的引用完整性的规则。 所以我们有: 创建表学生 ... 主键(学生代码) 外键(学号)引用学生(学号) 更新级联 删除级联 创建表学生 ... 主键(学生代码) 外键(学号)引用学生(学号) 更新级联 删除级联; 因此,我们看到在子实体类(或关系)“Student”中指定了一个主外键,它引用父实体类(或关系)“Students”。 维护引用完整性的级联规则决定了当父实体类“Students”的属性被删除或更新时,子关系“Student”的相应属性将被自动(级联)更新或删除。 同样,当父实体类“Students”的属性被删除或更新时,子关系“Students”的相应属性也会自动更新或删除。 需要注意的是,这里使用的是这个引用完整性规则,因为在这个上下文中(学生列表)禁止删除和更新信息是不合理的,并且还分配了一个未定义的值而不是真实的信息. 现在让我们举例说明上图中描述的实体类,仅以表格形式呈现。 因此,我们有以下关系表: 学生们 - 结合所有其他关系的属性信息的父关系: 学生 - 子女关系: 学生 - 第二个孩子关系: 博士生 - 第三个孩子关系: 因此,实际上,我们看到实体的子类不包含有关学生(即小学生、学生和研究生)的姓氏、名字和父名的信息。 这些信息只能通过对父实体类的引用来获得。 我们还看到“Students”实体类中不同的学生代码可以对应不同的子实体类。 因此,关于代码为“1”的学生 Nikolai Zabotin,父母关系中除了他的名字之外一无所知,所有其他信息(他是谁,男生,学生或研究生)只能通过参考找到到相应的子实体类(由代码确定)。 同样,您需要与其他学生一起工作,他们的代码在父实体类“学生”中指定。 5.组成 组合类型的实体类之间的关系,和前面两种一样,不属于递归关系的类型。 组成 (或者,有时被称为, 复合聚合) 是单个父实体类与多个子实体类的关系,就像我们上面讨论的关系一样。 概括。 但是如果将泛化定义为完全标识关系描述的实体类之间的关系,那么组合又是由不完全标识关系描述的,即在组合过程中,父实体类的主键的每个属性都迁移到键属性子实体类。 同时,迁移键属性只是部分构成了子实体类的主键。 因此,通过复合聚合(with composition),父实体类(或 单位) 与多个子实体类相关联(或 组件). 在这种情况下,聚合的组件(即父实体类的组件)通过作为主键一部分的外键引用聚合,因此不能存在于聚合之外。 一般来说,复合聚合是简单聚合的增强形式(我们稍后会谈到)。 组合(或复合聚合)的特征在于: 1) 对组件的引用涉及组件的标识; 2)这些组件不能存在于聚合之外。 具有必然非识别关系的聚合(我们将进一步考虑的关系)也不允许组件存在于聚合之外,因此在含义上接近于上述复合聚合的实现。 我们来构建一个描述一个父实体类和多个子实体类之间关系的关键图,即描述复合聚合类型的实体类之间的关系。 让这成为描绘某个校园建筑物组成的关键图,包括建筑物,它们的教室和电梯。 所以这张图看起来像这样: 那么让我们看一下我们刚刚创建的图表。 我们从中看到了什么? 首先,我们看到这个复合聚合中使用的关系确实是识别性的,而且确实不是完全识别性的。 毕竟,父实体类“Buildings”的主键参与了子实体类“Audiences”和“Elevators”的主键的形成,但并没有完全定义。 父实体类的主键“Case No”迁移到两个子类的外主键“Case No”,但是,除了这个迁移的键,两个子实体类还有自己的主键,分别是“Audience No”和“Elevator No.”,即子实体类的组合主键只是父实体类主键的部分构成属性。 现在让我们看看连接父类和两个子类的链接的多样性。 由于我们正在处理不完全识别的链接,因此存在多重性:“一个”和“许多”。 多重性“一”出现在两个关系的父端,表示在所有可用语料库的列表中(实体类“语料库”就是这样一个列表),每个数字只能出现一次,(不能再出现)比那个)次。 反过来,在“观众”和“电梯”类的属性中,每个楼号可以出现多次,因为观众(或电梯)多于建筑物,并且在每个建筑物中有多个礼堂和电梯。 因此,在列出所有教室和电梯时,我们不可避免地会重复楼号。 最后,和之前的连接类型一样,让我们写下用于创建基本关系(或者,这是同一事物,实体类)“Audiences”和“Elevators”的运算符的片段,我们将使用用于维护级联类型的引用完整性的规则定义来执行此操作。 所以这个声明看起来像这样: 创建表受众 ... 主键(语料库编号,受众编号) 外键(案例编号)引用模式(案例编号) 更新级联 删除级联 创建表升降机 ... 主键(案例号,电梯号) 外键(案例编号)引用模式(案例编号) 更新级联 删除级联; 因此,我们已经设置了子实体类的所有必要的主键和外键。 我们再次将保持参照完整性的规则视为级联,因为我们已经将其描述为最合理的。 现在我们将以表格形式给出我们刚刚考虑的所有实体类的示例。 让我们以图表的形式描述我们所反映的那些基本关系,为了清楚起见,我们将在那里引入一定数量的指示性数据。 住房 父关系如下所示: 观众 - 子实体类: 电梯 - 父类“Enclosures”的第二个子实体类: 因此,我们可以看到该数据库中所有建筑物、教室和电梯的信息是如何组织的,任何现实生活中的教育机构都可以使用这些信息。 6.聚合 聚合是实体类之间的最后一种关系,将被视为我们课程的一部分。 它也不是递归的,并且它的两种类型之一在含义上与之前考虑的复合聚合非常接近。 因此, 聚合 是一个父实体类与多个子实体类的关系。 在这种情况下,关系可以用两种类型的关系来描述: 1) 必须是非识别链接; 2) 可选的非识别链接。 回想一下,必然非标识关系,父实体类的主键的一些属性被转移到子类的一个非键属性,并且禁止迁移键的所有属性为空值。 并且在不一定是非标识关系的情况下,主键的迁移根据完全相同的原则发生,但允许迁移键的某些属性为空值。 聚合时,父实体类(或 单位) 与多个子实体类相关联(或 组件). 聚合的组件(即父实体类)通过不属于主键的外键引用聚合,因此,在这种情况下 不一定非识别关系,聚合组件可以存在于聚合之外。 在必然非标识关系的聚合中,聚合的成分不允许存在于聚合之外,从这个意义上说,必然非标识关系的聚合接近复合聚合。 现在已经清楚了什么是聚合类型关系,让我们构建一个描述这种关系操作的关键图。 让我们的未来图描述汽车的标记部件(即发动机和底盘)。 同时,我们假设汽车的退役意味着底盘随之退役,但并不意味着发动机同时退役。 所以我们的关键图是这样的: 那么我们在这个关键图中看到了什么? 首先,父实体类“Cars”与子实体类“Engines”的关系不一定是非标识的,因为属性“car#”允许其值之间存在空值。 反过来,此属性允许空值,因为根据条件,发动机的退役不依赖于整车的退役,因此,在汽车退役时不一定会发生。 我们还看到“Cars”实体类的“Engine#”主键迁移到了“Engines”实体类的非键属性“Engine#”。 同时,这个属性获得了外键的状态。 而这个Engines实体类中的主键是Engine Marker属性,不引用父关系的任何属性。 其次,父实体类“Motors”和子实体类“Chassis”之间的关系必然是非标识关系,因为外键属性“Car#”不允许其值之间存在Null值。 反过来,发生这种情况是因为根据条件已知汽车的退役意味着底盘的强制性同时退役。 这里和之前的关系一样,将父实体类“Motors”的主键迁移到子实体类“Chassis”的非键属性“Car number”。 同时,这个实体类的主键是“Chassis Marker”属性,不引用“Motors”父关系的任何属性。 前进。 为了最好地理解主题,让我们再次写下用于创建基本关系“电机”和“底盘”的运算符片段以及维护参照完整性的规则定义。 创建表引擎 ... 主键(电机标记) 外键(车号)引用 Cars(车号) 更新级联 在删除集 Null 创建表底盘 ... 主键(机箱标记) 外键(车号)引用 Cars(车号) 更新级联 删除级联; 我们看到我们使用相同的规则来维护所有地方的引用完整性 - 级联,因为我们甚至更早地认识到它是所有规则中最合理的。 但是,这次我们使用了(除了级联规则之外)set Null 引用完整性规则。 此外,我们在以下条件下使用它:如果删除父实体类“Cars”中主键“Car number”的某些值,则子关系“Engines”的外键“Car number”的值引用它将被分配一个 Null-value 。 7.属性的统一 如果在某个父实体类的主键迁移过程中,不同父类的意义一致的属性进入了同一个子类,那么这些属性必须进行“合并”,即需要进行so -叫 属性统一. 例如,一个员工可以在一个组织工作,不超过一个部门,统一“组织代码”属性后,得到如下关键图: 将主键从父实体类“Organization”和“Departments”迁移到子类“Employees”时,属性“Organization ID”进入实体类“Employees”。 两次: 1)第一次使用标记 PF建立不完全识别关系时来自实体类“Organization”的K; 2)和第二次,在建立不一定是非识别关系时,带有FK标记,条件是接受来自“部门”实体类的Null-values。 统一后,“Organization ID”属性具有主/外键属性的状态,吸收外键属性的状态。 让我们构建一个新的关键图来演示统一过程本身: 因此,发生了属性的统一。 第十三讲 专家系统与知识生产模型 1.专家系统的任命 为我们熟悉这样一个新概念 专家系统 首先,我们将回顾“专家系统”方向的创建和发展历史,然后我们将定义专家系统的概念。 在80年代初期。 XNUMX世纪在人工智能的创造研究中,形成了一个新的独立方向,叫做 专家系统. 这项关于专家系统的新研究的目的是开发旨在解决特定类型问题的特殊程序。 这种需要创建全新知识工程的特殊问题是什么? 这种特殊类型的任务可以包括来自任何主题领域的任务。 它们与普通问题的主要区别在于,对于人类专家来说,解决它们似乎是一项非常困难的任务。 那么第一个所谓的 专业系统 (专家的角色不再是人,而是机器),专家系统收到的结果在质量和效率上不逊色于普通人——专家。 专家系统的工作结果可以在非常高的层次上向用户解释。 专家系统的这种质量是由他们对自己的知识和结论进行推理的能力保证的。 专家系统很可能在与专家交互的过程中补充自己的知识。 因此,可以完全有信心将它们与完全形成的人工智能相提并论。 专家系统领域的研究人员为其学科名称也经常使用前面提到的术语“知识工程”,德国科学家 E. Feigenbaum 将其引入为“将人工智能领域的研究原理和工具用于解决问题需要专业知识的困难应用问题。” 然而,开发公司并没有立即取得商业上的成功。 从 1960 年到 1985 年,整整四分之一个世纪。 人工智能的成功主要与研究发展有关。 然而,从 1985 年左右开始,从 1987 年到 1990 年大规模进行。 专家系统已被积极地用于商业应用。 专家系统的优点是相当大的,如下: 1) 专家系统技术显着扩大了在个人计算机上解决实际重要任务的范围,其解决方案带来了显着的经济效益,并大大简化了所有相关过程; 2) 专家系统技术是解决传统编程的全球性问题的最重要工具之一,例如持续时间、质量以及因此开发复杂应用程序的高成本,因此经济效果显着降低; 3)复杂系统运维成本高,往往超过开发本身成本数倍,程序复用性低等; 4) 专家系统技术与传统编程技术的结合为软件产品增加了新的品质,首先,由普通用户而不是程序员提供应用程序的动态修改; 其次,应用程序的“透明度”更高,专家系统的图形、界面和交互更好。 根据普通用户和领先专家的说法,在不久的将来,专家系统将有以下应用: 1) 专家系统将在设计、开发、生产、分销、调试、控制和服务交付的各个阶段发挥主导作用; 2) 得到广泛商业应用的专家系统技术将为现成的智能交互模块的应用集成提供革命性的突破。 一般来说,专家系统是为所谓的 非正式任务,即专家系统不会拒绝也不会取代专注于解决形式化问题的传统程序开发方法,而是对其进行补充,从而显着扩大可能性。 这正是单纯的人类专家无法做到的。 这种复杂的非形式化任务的特点是: 1) 源数据的谬误、不准确、含糊、不完整和不一致; 2) 关于问题领域和正在解决的问题的谬误、歧义、不准确、不完整和不一致的知识; 3) 特定问题解空间的大维数; 4) 直接在解决此类非正式问题的过程中数据和知识的动态可变性。 专家系统主要基于对解决方案的启发式搜索,而不是基于已知算法的执行。 这是专家系统技术相对于传统软件开发方法的主要优势之一。 这就是使他们能够很好地应对分配给他们的任务的原因。 专家系统技术用于解决各种问题。 我们列出了这些任务的主要内容。 1. 解释. 执行解释的专家系统最常使用各种仪器的读数来描述事态。 解释性专家系统能够处理各种类型的信息。 一个例子是使用光谱分析数据和物质特性的变化来确定它们的成分和性质。 还有一个例子是解释锅炉房中测量仪器的读数,以描述锅炉的状态和其中的水。 解释系统通常直接处理读数。 在这方面,出现了其他类型系统没有的困难。 这些困难是什么? 这些困难的出现是由于专家系统必须解释堵塞的多余、不完整、不可靠或不正确的信息。 因此,错误或数据处理的显着增加是不可避免的。 2. 预测. 执行某事预测的专家系统确定给定情况的概率条件。 例如,预测恶劣天气条件对粮食收成造成的损害、评估世界市场对天然气的需求、根据气象站进行天气预报。 预测系统有时会使用建模,即显示现实世界中某些关系的程序,以便在编程环境中重新创建它们,然后设计某些初始数据可能出现的情况。 3. 各种设备的诊断. 专家系统通过使用任何情况、行为的描述或各种组件结构的数据来执行此类诊断,以确定可诊断系统故障的可能原因。 例如,通过在患者身上观察到的症状来确定疾病的情况(在医学上); 识别电子电路中的故障和识别各种设备机制中的故障组件。 诊断系统通常是助手,不仅可以进行诊断,还可以帮助排除故障。 在这种情况下,这些系统可以很好地与用户交互以协助进行故障排除,然后提供解决这些问题所需的操作列表。 目前,正在开发许多诊断系统作为工程和计算机系统的应用程序。 4. 策划各种活动. 专为规划设计各种操作而设计的专家系统。 系统在开始实施之前预先确定了几乎完整的操作序列。 这种事件规划的例子是制定军事行动计划,包括防御性和进攻性,预先确定一定时期,以便获得对敌军的优势。 5. 设计. 执行设计的专家系统开发各种形式的对象,同时考虑到普遍情况和所有相关因素。 一个例子是基因工程。 6. 控制. 执行控制的专家系统将系统的当前行为与其预期行为进行比较。 观察专家系统检测受控行为,确认他们的预期与正常行为或他们对潜在偏差的假设。 控制专家系统,就其本质而言,必须实时工作,并对受控对象的行为进行时间相关和上下文相关的解释。 示例包括监测核反应堆中测量仪器的读数以检测紧急情况或评估重症监护病房患者的诊断数据。 7. 管理. 毕竟,众所周知,执行控制的专家系统可以非常有效地管理整个系统的行为。 一个例子是各个行业的管理,以及计算机系统的分布。 控制专家系统必须包括观察组件,以便在很长一段时间内控制对象的行为,但它们可能还需要来自已分析任务类型的其他组件。 专家系统用于各个领域:金融交易、石油和天然气工业。 专家系统技术还可以应用于能源、交通、制药、航天开发、冶金矿业、化学等诸多领域。 2. 专家系统结构 专家系统的开发与传统软件产品的开发有许多显着差异。 创建专家系统的经验表明,在开发过程中使用传统编程中采用的方法论,要么大大增加创建专家系统所花费的时间,甚至会导致负面结果。 专家系统一般分为 静止的 и 动态. 首先,考虑一个静态专家系统。 标准 静态专家系统 由以下主要部分组成: 1)工作记忆,也叫数据库; 2)知识库; 3)求解器,也称为解释器; 4)知识获取的组成部分; 5) 解释性成分; 6)对话框组件。 现在让我们更详细地考虑每个组件。 工作记忆 (通过与工作的绝对类比,即计算机 RAM)旨在接收和存储当前正在解决的任务的初始和中间数据。 知识库 旨在存储描述特定主题领域的长期数据,以及描述正在解决的问题的该领域数据合理转换的规则。 求解器也叫 口译员,功能如下:使用来自工作记忆的初始数据和来自知识库的长期数据,它形成规则,将其应用于初始数据导致问题的解决方案。 总之,他真的“解决”了摆在他面前的问题; 知识获取部分 使用专家知识填充专家系统的过程自动化,即正是这个组件为知识库提供了来自该特定主题领域的所有必要信息。 解释组件 解释系统如何获得这个问题的解决方案,或者为什么它没有收到这个解决方案,以及它在这样做时使用了哪些知识。 换句话说,解释组件生成进度报告。 该组件在整个专家系统中非常重要,因为它极大地方便了专家对系统的测试,也增加了用户对所获得结果的信心,从而加快了开发过程。 对话框组件 用于在解决问题的过程中以及在获取知识和声明工作结果的过程中提供友好的用户界面。 现在我们知道了统计专家系统通常由哪些组件组成,让我们构建一个反映此类专家系统结构的图表。 它看起来像这样: 静态专家系统最常用于技术应用中,在这些应用中可能不考虑在解决问题期间发生的环境变化。 令人好奇的是,第一批获得实际应用的专家系统恰恰是静态的。 那么,到此我们就暂时结束对统计专家系统的考虑,下面继续对动态专家系统进行分析。 不幸的是,我们课程的程序不包括对该专家系统的详细考虑,因此我们将仅限于分析动态专家系统和静态专家系统之间最基本的区别。 与静态专家系统不同,结构 动态专家系统 此外,还引入了以下两个组件: 1) 外部世界建模子系统; 2)与外部环境关系的子系统。 与外部环境关系的子系统 它只是与外界建立联系。 她通过一个特殊的传感器和控制器系统来做到这一点。 此外,静态专家系统的一些传统组件经历了重大变化,以反映环境中当前发生的事件的时间逻辑。 这是静态和动态专家系统之间的主要区别。 动态专家系统的一个例子是制药行业中各种药物生产的管理。 3. 专家系统开发的参与者 各种专业的代表都参与了专家系统的开发。 大多数情况下,一个特定的专家系统是由三位专家开发的。 这通常是: 1)专家; 2)知识工程师; 3) 程序员的开发工具。 让我们解释这里列出的每一位专家的职责。 专家 是该学科领域的专家,其任务将在这个正在开发的特定专家系统的帮助下得到解决。 知识工程师 是直接开发专家系统的专家。 他所采用的技术和方法称为知识工程技术和方法。 知识工程师帮助专家从主题领域的所有信息中识别出与正在开发的特定专家系统一起工作所必需的信息,然后对其进行结构化。 奇怪的是,开发参与者中知识工程师的缺席,即他们被程序员取代,要么导致创建特定专家系统的整个项目失败,要么显着增加其开发时间。 最后, 程序员 开发旨在加速专家系统开发的工具(如果是新开发的工具)。 这些工具最多包含专家系统的所有主要组件; 程序员还将他的工具与将要使用的环境连接起来。 4. 专家系统的运行模式 专家系统以两种主要模式运行: 1)获取知识的方式; 2)解决问题的方式(也称咨询方式,或专家系统方式)。 这是合乎逻辑且可以理解的,因为首先有必要将专家系统必须工作的主题领域的信息加载到专家系统中,这是专家系统的“培训”模式,当它接受知识。 在加载了工作所需的所有信息之后,工作本身就会随之而来。 专家系统准备好运行,现在可以用于咨询或解决任何问题。 让我们更详细地考虑 知识获取模式. 在获取知识的模式中,专家系统的工作是由专家通过知识工程师来完成的。 在这种模式下,专家使用知识获取组件向系统填充知识(数据),从而使系统可以在没有专家参与的情况下以解决方案解决来自该主题领域的问题。 需要说明的是,传统程序开发方式中的知识获取模式对应的是程序员直接进行算法化、编程和调试的阶段。 由此可见,与传统方法相比,在专家系统的情况下,程序的开发不是由程序员进行的,而是由专家进行的,当然,在专家系统的帮助下,即大体上,一个不懂编程的人。 现在让我们考虑专家系统的第二种运行模式,即 问题解决模式. 在问题解决模式(或所谓的咨询模式)中,与专家系统的交流直接由最终用户进行,他们对工作的最终结果感兴趣,有时甚至对获得结果的方法感兴趣。 应该注意的是,根据专家系统的目的,用户不必是该问题领域的专家。 在这种情况下,他求助于专家系统以获得结果,但没有足够的知识来获得结果。 或者,用户可能仍具有足够的知识水平以自行实现期望的结果。 在这种情况下,用户可以自己得到结果,但求助于专家系统以加快获得结果的过程,或者将单调的工作分配给专家系统。 在咨询模式下,用户的任务数据经过对话组件处理后,进入工作记忆。 求解器基于来自工作记忆的输入数据、有关问题区域的一般数据以及来自数据库的规则,生成问题的解决方案。 在解决问题时,专家系统不仅执行规定的特定操作顺序,而且初步形成它。 这是针对用户不完全清楚系统反应的情况。 在这种情况下,用户可能需要解释为什么这个专家系统会问一个特定的问题或者为什么这个专家系统不能执行这个操作,这个或那个专家系统提供的结果是如何获得的。 5.知识生产模式 在它的核心, 知识生产模型 接近逻辑模型,这使您可以组织非常有效的逻辑数据推理过程。 这是一方面。 但是,另一方面,如果我们将知识的生产模型与逻辑模型进行比较,那么前者更清晰地展示知识,这是无可争辩的优势。 因此,毫无疑问,知识的生产模型是人工智能系统中知识表示的主要手段之一。 那么,让我们开始详细考虑知识生产模型的概念。 传统的知识生产模型包括以下基本组成部分: 1) 代表产生式系统知识库的一组规则(或产生式); 2)工作记忆,存储原始事实,以及利用推理机制从原始事实中推导出的事实; 3)逻辑推理机制本身,它允许根据现有的推理规则,从可用的事实中推导出新的事实。 而且,奇怪的是,此类操作的数量可以是无限的。 表示生产系统知识库的每个规则都包含一个条件部分和一个最终部分。 规则的条件部分包含单个事实或由连词连接的多个事实。 如果规则的条件部分为真,规则的最后部分包含需要用工作记忆补充的事实。 如果我们试图示意性地描述知识的生产模型,那么生产被理解为以下形式的表达: (i) 问; ; A→B; 否; 这里 i 是知识生产模型的名称或其序列号,借助它可以将此生产与整套生产模型区分开来,并获得某种标识。 一些反映该产品本质的词汇单元可以作为名称。 事实上,我们命名产品是为了更好地通过意识感知,以简化从列表中搜索所需产品的过程。 让我们举一个简单的例子:买一本笔记本”或“一套彩色铅笔。 显然,每个产品通常都用适合当下的词语来指代。 换句话说,直言不讳。 前进。 Q 元素描述了这个特定知识生产模型的范围。 这些领域在人的头脑中很容易区分,因此,通常来说,这个元素的定义没有困难。 让我们举个例子。 让我们考虑以下情况:假设我们意识的一个区域存储了如何烹饪食物的知识,另一个区域存储了如何上班,第三个区域存储了如何正确操作洗衣机。 类似的划分也存在于知识生产模型的记忆中。 这种将知识划分为不同领域的方法可以显着节省寻找当前所需的某些特定知识生产模型所花费的时间,从而大大简化使用它们的过程。 当然,生产的主要要素是它的所谓核心,在我们上面的公式中表示为A→B。这个公式可以解释为“如果满足条件A,则应该执行动作B”。 如果我们正在处理更复杂的内核构造,则右侧允许以下替代选择:“如果满足条件 A,则应执行操作 B1, 否则你应该执行动作 B2". 但是,对知识生产模型核心的解释可能会有所不同,这取决于后续符号“→”的左侧和右侧是什么。 通过对知识生产模型核心的解释之一,后续可以在通常的逻辑意义上进行解释,即作为动作 B 从真实条件 A 的逻辑结果的标志。 尽管如此,对知识生产模型核心的其他解释也是可能的。 因此,例如,A 可以描述一些条件,为了执行某些操作 B,必须满足该条件。 接下来,我们考虑知识生产模型 R 的一个元素。 元素 Р 被定义为产品核心适用性的条件。 如果条件 P 为真,则生产核心被激活。 否则,如果不满足条件 P,即为假,则无法激活核心。 作为说明性示例,请考虑以下知识生产模型: “资金可用性”; “如果你想买东西 A,那么你应该把它的成本付给收银员,然后把支票出示给卖家。” 我们看,如果条件P为真,即购买已支付,支票已出示,那么核心就被激活了。 购买完成。 如果在这个知识生产模型中,核心的适用条件是假的,即如果没有钱,那么就不可能应用知识生产模型的核心,它就不会被激活。 最后转到元素 N. 元素 N 称为生产数据模型的后置条件。 后置条件定义了在生产核心实施后必须执行的操作和过程。 为了更好的理解,我们举一个简单的例子:在商店购买了一件东西后,需要在这家商店的商品库存中将这种东西的数量减少一个,即如果购买了(因此, 核心已售出),则商店将此特定产品的一个单位变小。 因此,后置条件“划掉购买物品的单位”。 综上所述,我们可以说,将知识表示为一组规则,即通过使用知识生产模型,具有以下优点: 1) 易于创建和理解个人规则; 2)是逻辑选择机制的简单性。 然而,在以一组规则的形式表示知识时,也存在一些不足,仍然限制了生产知识模型的应用范围和频率。 主要的缺点是构成特定知识生产模型的规则之间的相互关系的模糊性,以及逻辑选择的规则。 笔记 1. 本书印刷版中划线字体对应 加粗斜体 在这本书的(电子)版本中。 (大约 e.ed.) 我们推荐有趣的文章 部分 讲义、备忘单: 查看其他文章 部分 讲义、备忘单. 读和写 有帮助 对这篇文章的评论. 科技、新电子最新动态: 用于触摸仿真的人造革
15.04.2024 Petgugu全球猫砂
15.04.2024 体贴男人的魅力
14.04.2024
其他有趣的新闻: ▪ 微软多点触控鼠标 ▪ 益生菌与怀孕 ▪ 发现四中子
免费技术图书馆的有趣材料: 本页所有语言 www.diagram.com.ua |