数据库理解知识点

文章目录

      • 数据库概述
      • 数据库模型
        • 概念模型
        • 逻辑模型
          • 层次模型
          • 网状模型
          • 关系模型
        • 数据库系统模式概念
      • 关系数据库
      • 关系操作
      • 关系的完整性
      • SQL之数据定义
      • SQL之数据查询
        • 单表查询
        • 多表查询(连接查询)
        • 嵌套查询
        • 集合查询
        • 基于派生表的查询
      • 数据更新
      • 视图
      • 数据库安全性
      • 数据库完整性
      • 关系数据理论
      • 数据库设计
      • 查询优化
        • 数据库恢复技术
      • 并发控制

数据库概述

  1. 数据是描述事物的记录符号。
  2. 数据库是长期存储在计算机内,有组织的、可共享的大量数据的集合。
  3. 数据库的特点永久存储,有组织的、可共享的
  4. DBS由DB,DBMS,应用程序,数据库管理员组成的存储、管理、处理和维护数据的系统。
    DBS(数据库系统);
    DB(数据库)宿主:具有访问该数据库权限的用户;
    DBMS(数据库管理系统):数据定义功能,数据组织、存储、管理,数据操纵功能,运行管理,建立维护功能
  5. 数据管理三个阶段人工管理、文件系统、数据库系统。
  6. 人工管理阶段的特点:数据不保存、数据不共享、数据不具有独立性、应用程序管理数据。
  7. 文件系统阶段的特点:数据可以保存、由文件系统管理数据、共享性差、冗余度大、数据独立性差。
  8. 数据库系统阶段的特点:整体数据的结构化(把数据归类化到不同表中,降低冗余,方便管理)、数据的共享性高、冗余度低且易扩充、独立性高(数据独立性、逻辑独立性、物理独立性)。
    逻辑独立性:指用户的应用程序与数据库中数据的逻辑存储是相互独立的。
    物理独立性:指用户的应用程序与数据库中数据的物理存储是相互独立的。
  9. 数据控制功能:**数据的安全性保护、完整性保护、并发控制、数据库恢复 **
    数据的安全性是指保护数据以防止不合法使用造成数据的泄露和破坏。
    数据的完整性是指数据的正确性、有效性和相容性。
    并发控制是避免多用户同时存取、修改数据库导致数据库完整性的破坏
    数据库恢复是指计算机的软硬件破坏、操纵员的失误/故意破坏后,将数据库恢复到某已知的正确状态。

数据库模型

  1. 数据模型是对现实世界数据特征的抽象。
  2. 数据模型分为概念模型、逻辑模型/物理模型两大类。
  3. 概念模型是从用户角度进行模拟,主要用于数据库的设计。
  4. 逻辑模型和物理模型是从计算机角度进行模拟,主要用于数据库管理系统的实现。
  5. 逻辑模型包括层次模型、网状模型、关系模型、面向对象模型、对象关系模型、半结构化模型。
  6. 物理模型描述数据在系统内部、磁带、磁盘中表示方式和存取方法,物理模型是最底层的抽象
  7. 从现实世界到概念模型的转化是由数据库设计人员完成。
  8. 从概念模型到逻辑模型的转化是由数据库设计人员完成或数据库设计工具协助设计人员完成的。
  9. 从逻辑模型到物理模型的转化主要由数据库管理系统完成的。
  10. 数据模型三要素:数据结构,数据操作(增删改查),数据完整性约束
  11. 数据结构描述数据库的组成对象以及对象之间的联系
  12. 数据操作是指对数据库中各种对象的实例允许的操作的集合,包括操作及有关的操作内容。
  13. 数据完整性是一组完整性规则

概念模型

  1. 基本概念
    :唯一标识实体属性集
    :一组具有相同数据类型的值集合
    实体:客观存在并可以相互区别的事物
    属性:实体所具有的某一特性
    实体集:同一类型实体集合
    弱实体:依赖于父实体存在而存在
    目/度:列个数
  2. 概念模型的表达方式:实体-联系方法(E-R图)
    .

逻辑模型

层次模型
  1. 树型结构来表示各类实体以及实体间的联系,层次模型只能处理一对多(包括一对一)的实体联系,但多对多联系可以拆分为一对多来表示。
  2. 有且只有一个结点没有双亲结点;
  3. 根以外的其他结点有且只有一个双亲结点;
  4. 任何一个给定的记录只能按层次路径进行查看;
  5. 没有一个子女记录能脱离双亲记录指而独立存在的。
  6. 层次模型的数据操作有增删改查,其中增删改需要满足数据完整性。
    进行插入操作:没有相应双亲结点值就不能插入它的子女结点值。
    进行删除操作:删除双亲结点值,则相应的子女结点值同时也被删除
  7. 层次模型的优点:结构简单清晰,查询效率高(性能高于关系模型,低于网状模型)、具有良好的完整性支持。
  8. 层次模型的缺点:现实世界中很多联系是非层次性的,结点有多个双亲结点时比较笨拙,查询必须通过双亲结点,结构严密层次命令趋于程序化。
网状模型
  1. 网状模型允许无双亲,多双亲。
  2. 子女结点和双亲姐弟的联系可以不唯一
  3. 网状模型的优点:存储效率高
  4. 网状模型的缺点:复杂
关系模型
  1. 关系:一个关系一张表
  2. 元组:一行即一个元组
  3. 属性:一列即一个属性
  4. 码(码键):某个属性组唯一确定一个元组。码是属性组。
  5. 域:一组具有相同数据类型的值得集合。
  6. 分量:元组中的一个属性值。
  7. 关系模式:实体型 关系名(属性1,属性2,…)
  8. 关系必须规范化,关系的的分量必须是不可分割的数据项。
  9. 关系的完整性约束条件为:实体完整性、参照完整性、用户定义完整性。
  10. 关系的数据操作是集合操作,操作对象和操作结果都是关系。
    关系数据库的优点:建立严格数学概念,关系模型概念单一,关系模型存取路径对用户透明独立保密(用户只要指出干什么或找什么,不必详细说明怎么干或怎么找);
    关系数据库的缺点:查询效率低。

数据库系统模式概念

  1. 数据库系统采用三级模式两级映像功能
  2. 模式:数据库中全体数据的逻辑结构和特征的描述,是所有用户的公共数据视图,一个数据库只有一个模式。
  3. 外模式(用户模式):用户能够看见和使用局部数据的逻辑结构和特征的描述,用户可见视图,是模式子集;一个数据库有多个外模式(一个应用程序只用一个外模式)。
  4. 内模式(存储模式):内模式是数据物理结构和存储方式的描述,是数据在数据库内部的组织方式。
  5. 两级映像:外模式/模式,模式/内模式
    逻辑独立性:模式改变。外模式/模式映像做出改变,使外模式保持不变保证了数据和程序的逻辑独立性。
    物理独立性:存储结构改变,对模式/内模式做出相应改变,使模式不变保证了数据和应用程序物理独立性。
  6. 数据三级模式引入两级映像作用:提高数据与程序的独立性。

关系数据库

  1. 候选码:某一属性组的值唯一标识一个元组,而其子集不能。
  2. 主码:一个关系中有多个候选码,选择其中一个候选码作为主码。
  3. 主属性:候选码中的所有属性为主属码。
  4. 非主属性\非码属性:不包含在候选码中的属性为非主属性。
  5. 关系三中类型:基本关系、查询表和视图表。
  6. SQL:结构化查询语言是集查询、数据定义语言DDL、数据操纵语言DML和数据控制语言DCL于一体的关系数据语言。

关系操作

  1. 5种基本关系操作:选择、投影、并、差、笛卡尔积
  2. 并(union):由属于R或属于S的元组组成
  3. 差(except):由属于R而不属于S的所有元组组成
  4. 笛卡尔积(cartesian product)
  5. 选择(selection):在关系中R中选择满足给定条件的诸元组,操作对象是行。
  6. 投影(projection):从关系R中选择出若干属性组成新的关系,操作对象是列。
  • 以下复杂的关系操作
  1. 交(intersection):即属于R又属于S的元组组成。
  2. 连接(join):从两个关系的笛卡尔积中选取属性(可以不同名)间满足一定的条件的元组。
    非等值连接:从两个关系的笛卡尔积中选取属性(可以不同名)间满足非相等的条件的元组。
    等值连接(equijoin):从两个笛卡尔积中选取属性(可以不同名)值相同的元组。
    自然连接(natural join):是一种特殊的等值连接,必须是同名属性组,在结果中将重复的属性列去掉。
  3. 悬浮元组(dangling tupe):两个关系自然连接中,可能有不存在公共属性值相等的元组。
  4. 外连接(outer join):把悬浮元组保存在结果关系中,在其他属性中填空值(NULL) 。
  5. 左外连接(lefe outer join):只保留左边关系R的悬浮元组
  6. 右外连接(right outer join):只保留右边关系S的悬浮元组
  7. 除运算(division):设关系R除以关系S的结果为关系T,则T包含在所有在R但不在S中的属性及其值,且T的元组与S元组的所有组合都在R中。

关系的完整性

  1. 3类完整性约束条件:实体完整性、参照完整性和用户定义的完整性。
  2. 实体完整性:主属性不能取空值(不知道、不存在、无意义)。
  3. 参照完整性:参照表中的参照属性必须是空值或等于被参照属性中的值。
  4. 用户定义完整性:
    空值:空值的判断用:is null或is not null。

SQL之数据定义

  1. 模式的定义和删除
    创建模式:create schema <模式名> authorization <用户名>
    删除模式:drop schema <模式名>
  2. 基本表的定义、删除、修改
    基本表的定义:create table <表名> (<列名1><数据类型>[约束条件], …)
    基本表的删除:drop table
    基本表的修改:alter table
  3. restrict:删除表示时受限,基本表不能被其他表的约束引用,不能有视图,不能有触发器。
  4. cascade:删除基本表时,删除相关依赖。
  5. 索引的建立与删除
    索引的类型:顺序文件上的索引,B+树索引(具有动态平衡的优点),散列索引,位图索引。
    索引的建立:create [unique| cluster] index
    unique:表明此索引的每一个索引只对应一个唯一的数据记录(在一列上取唯一,要求这一列数据各不相同)。
    cluster:表示聚簇索引,一个表最多一个聚簇索引
    索引的删除:drop index <索引名>
    索引的修改:alter index <旧索引名> rename to <新索引名>

SQL之数据查询

单表查询

  1. 选择表中的若干
    查询指定的列 select Sno, Sname
    查询所有的列 select *
    查询经过计算的值 select Sname, 2020-Sage
  2. 选择表中的若干元组
    消除取值重复的行:select distinct Sno
    查询满足条件的元组:select Sname,Sage from table where XXX(查询条件)
  3. 排序
    利用order by语句对查询结果按照一个或多个属性的升序(ASC)或降序(DESC),默认为升序。
  4. 聚集函数
    count*:统计元组的个数
    count [distinct|all] <列名>:统计一列中值得个数
    sum [distinct|all] <列名>:计算一列的和
    avg [distinct|all] <列名>:计算一列的平均值
    max [distinct|all] <列名>:求一列的最大值
    min [distinct|all] <列名>:求一列的最小值
    聚集函数只能用于select语句和group by中having子句。
    Where和Having的区别:where作用于基本表或者视图,筛选记录,HAVING筛选组,用于分组
  5. group by
    group by:将查询结果按照某一列或多列的值进行分组,值相同的为一组。
    分组后,聚集函数将作用于每一个组,即每一个组都有一个函数值。
    having:用来指定筛选条件
  6. 关于查询条件的补充
    比较大小:=,<,>,>=,<=,!=,!>,!<
    确定范围:between…(低值)and…(高值)
    确定集合in:用谓词lin可以查找属性值指定集合的元组。
    字符匹配:用谓词like进行字符串匹配,%表示任意长度的字符串,_表示当个字符,转义字符escape ‘’
    空值查询:is null/ is not null
    多重条件查询:and

多表查询(连接查询)

  1. 等值与非等值连接查询:格式:[<表1>]<列名1><比较运算符>[<表2>]<列名2>
    当连接运算符为=时,为等值连接。
    当连接运算符为其他时,为非等值连接。
    连接谓词中的列名为连接字段,连接字段的数据类型必须可比的,名字可以不一样。
  2. 自身连接:一个表与其自己进行连接,要取别名。
  3. 外连接:保存悬浮元组。
  4. 多表查询

嵌套查询

  1. 查询块:一个select-from-where语句为查询块
  2. 嵌套查询:将一个查询块嵌套另外一个查询块的where子句或having短语中。
  3. 上层查询/父查询 嵌套 内层查询/子查询。
  4. 带谓词IN的子查询:
    不相关子查询:子查询的查询条件不依赖于父查询。一种求解方法是由里向外处理,向执行子查询,子查询的结果用于建立其父查询的查找条件。
    相关子查询:子查询的查询条件依赖于父查询,有关内层查询和外层查询故求解方法必须反复子查询。
  5. 带有比较运算符的子查询:带有比较运算符的子查询是指父查询和子查询之间用比较运算符进行连接。
  6. 带有ANY(SOME)、ALL谓词的子查询
  7. 带有exists谓词的子查询:子查询不返回任何数据,只产生逻辑True或False。

集合查询

  1. 集合查询将多个select语句的结果进行集合操作。
  2. 集合操作包括:并union,交intersect,差except。

基于派生表的查询

子查询出现在from中,此时子查询生成临时派生表。

数据更新

  1. 插入元组:insert
  2. 插入子查询结果:insert into<表名> 子查询;
  3. 修改一个元组:update <表名> set <> where 条件
  4. 修改多个元组:update <表名> set <>
  5. 修改带子查询的元组
  6. 删除一个元组:delete from<表名> where条件
  7. 删除多个元组:delete from<表名>
  8. 删除带子查询的元组

视图

  1. 建立视图:create view <视图名> [(<列名>)] as <子查询> [with check option]
  2. 行列子集视图:从单个基本表导出,并且只是去掉基本表的某些行或列,但保留主码的视图。
  3. 分组视图:带有聚集函数和Group by子句的查询来定义视图。
  4. DB2:
    视图由两个基本表导出,不允许更新;
    视图字段来自聚集函数,视图不允许更新
    视图定义含义Group by子句,视图不允许更新
    视图定义含有distinct(查询后去重),视图不允许更新
    视图定义含有嵌套查询并且内层查询涉及的表也是导出视图的基本表,视图不允许更新
    视图的字段来自字段表达式或常数,不允许对视图更新、插入,但允许删除
    一个不允许更新的视图上定义的视图也不允许更新。
  5. distinct和unique:distinct(查询后去重),unique在查询中去重。
  6. 视图的作用:简化用户操作,多种角度看待数据,逻辑独立性,数据保护,清晰表达查询

数据库安全性

  1. 数据库安全控制的常用方法:用户标识和鉴别、审计、存取控制、密码存储、视图。
  2. 授权:grant <权限> ON <对象名> TO <用户> with grant option
  3. with grant option:可以将权限传播给其他用户。
  4. 回收:revoke grant <权限> ON <对象名> FROM <用户> [cascade | restrict ]
  5. 数据库角色:数据的角色是被命名的一组与数据库操作相关的权限,角色是权限的集合。
  6. 用户身份鉴别:静态口令鉴别、动态口令鉴别、生物特征鉴别、智能鉴别。
  7. 自主存取控制:用户对于不同的数据库对象有不同的存取权限,不同的用户对同一对象也有不同的权限,而且用户还可以将拥有的存储权限转授给其他用户。
  8. 强制存取控制:每一个数据库对象被标以一定的密级,每一个用户被授予某一级别的许可证。
  9. 强制存取控制:
    当主体的许可证级别大于或等于客体的密级时,该主体才能读取相应的客体。
    当主体的许可证级别小于或等于客体的密级时,该主体才能写相应的客体。
  10. 视图机制:把保密的数据对无权存取的用户影藏起来。
  11. 审计:用户对数据库的所有操作自动记录下来放入审计日志。
  12. 数据加密

数据库完整性

  1. 完整性是指数据的正确性和相容性。
  2. 实体完整性:
    检查主码值是否唯一,如果不唯一则拒绝插入或修改;
    检查主码的各个属性是否为空,只要有一个为空就拒绝插入或修改。
    primary key定义主码
  3. 参照完整性:
    用foreign key定义参照表中那些列作为外码
    用referemces定义外码参照那些表的主码
    参照表插入元组或修改外码值,破坏参照完整性,违约处理是拒绝
    被参照表删除元组或修改主码,破坏参照完整性,违约处理是拒绝/级联删除/设置空值。
  4. 参照完整性的违约处理:
    拒绝执行(no action),一般是默认策略
    级联操作(cascade):修改或删除被参照表,导致不一致,则修改或删除参照表
    设置为空:修改或删除被参照表,导致不一致,则参照表中所造成不一致的元组的对应属性设置为空。
  5. 用户定义完整性
    列值非空(not null)
    列值唯一(unique)
    检查列值是否满足一个条件表达式(check短语)

关系数据理论

  1. 关系模式-五元组
    R(U, D, DOM, F)
    R:关系名
    U:一组属性
    D:属性组U中的属性所来自的域
    DOM:属性到域的映射
    F:属性组U上的一组数据依赖
  2. 关系模式存在问题:数据冗余,更新异常,插入异常,删除异常
  3. 数据依赖是一个关系内部属性与属性之间的一种约束条件。
  4. 函数依赖:关系模式R属性U上的两个属性X,Y,对于关系r不可能存在两个元组在X上相等,而在Y上属性不等,即Y函数依赖于X或者X->Y。例:(Sname) -> (age)
  5. 非平凡依赖 :X->Y,但是Y不是X的子集。例:(Sno, Cno)->(grade)
  6. 平凡依赖:X->Y,且Y是X的子集。例:(Sno, Cno)->(Sno)
  7. 多值依赖:关系模式R属性U,X,Y,Z是U子集,Z=U-X-Y,对于关系r给定值(x,z),有一组Y的值,这组值决定于x值而与z值无关;即X->->Y
  8. 完全函数依赖:左边无多余属性:X->Y,任何X真子集X1,有X1不能推出Y。
  9. 部分函数依赖:左边有多余属性,X->Y,存在X真子集X1,有X1->Y
  10. 传递函数依赖:X->Y且Y不是X的子集,Y不能函数依赖X,Y->Z且Z不是Y的子集。
  11. 直接函数依赖:双向传递函数依赖。
  12. 候选码是最小的超码,即超码的任意一个真子集都不是候选码。
  13. 主码:从候选码中选择一个候选码作为主码。
  14. 主属性:包含在任何一个候选码的属性称为主属性。
  15. 非主属性:不包含在任何候选码中的属性称为非主属性。
  16. 范式:关系数据库的关系满足一定要求。
  17. 规范化:一个低一级范式的关系模式通过模式分解可以转化为若干个高一级范式的关系模式的集合的过程。
  18. 1FN:表中不可有表,基本属性不可分割。
  19. 2FN:在1FN基础上,消除非主属性对主属性的部分依赖,让非主属性完全函数依赖于任何一个候选码
  20. 3FN:在2FN基础上,消除非主属性对主属性的传递函数依赖。
  21. BCNF:在3FN基础上,消除主属性,非主属性,对码的部分和传递函数依赖。
  22. 4FN:消除多值依赖
    数据库理解知识点_第1张图片

数据库设计

  1. 数据库设计的步骤:需求分析阶段、概念结构设计阶段、逻辑结构设计阶段、物理结构设计阶段、数据库实施阶段、数据库允许和维护阶段。
  2. 需求分析(数据字典:数据项,数据结构,数据流,数据存储,处理过程)
  3. 概念结构设计(ER,自顶向下,自底向上)
  4. 逻辑结构设计(关系模式)
  5. 物理结构设计(存储安排,索引)
  6. 实施阶段(SQL)
  7. E-R图:实体型用矩形表示,属性用椭圆形,联系用菱形。
  8. UML:统一建模语言
  9. 属性和实体区分规则:属性不可分,属性不能作为其他实体具有联系。
  10. E-R图冲突:属性,命名,结构
  11. 逻辑结构设计:
    1:1 :可以转化为一个独立关系模式,也可以与任意一端对应的关系模式合并。
    1:n :可以转化为一个独立关系模式,也可以与n端对应的关系模式合并。
    m:n :与该联系的各实体的码以及联系本身的属性转化为关系的属性

查询优化

  1. 查询处理步骤:查询分析,查询检查,查询优化,查询执行
  2. 优化原则
    选择尽可能先做
    投影选择同时进行
    把投影运算和选择运算同时进行,
    把某些选择和其前面要执行的笛卡尔积结合成一个连接运算
    公共子表达式
  3. 查询优化:选择-》连接-》笛卡尔积
  4. 代数优化策略是通过对关系代数表达式的等价变换来提高查询效率。

数据库恢复技术

  1. 事务是用户定义的一个数据库操作序列,这些操作要么全做,要么不全做,是一个不可分割的工作单位。
  2. 事务的4个特性:原子性,一致性,隔离性和持续性。
  3. 原子性:事务操作要么都做,要么都不做。
  4. 一致性:存入和取出要么全做,要么全不做。一个事务必须使数据库从一个一致性状态变换到另一个一致性状态
  5. 隔离性:多个并发执行的事务正确执行互不干涉。
  6. 持续性:事务一旦提交,对数据库的改变是永久的对DB的修改数据库中留下痕迹,永不消逝。
  7. 事务故障:某一程序(事务)自身运行错误;不会破坏数据库,只需日志就可以恢复事务故障;UNDO事务撤销。
  8. 系统故障(掉电):日志文件恢复;UNDO没有终止的事务,REDO已经提交的事务
  9. 介质故障:后备副本+日志文件可以恢复介质故障(动态转储系统也是后备副本+日志)
    事务未提交UNDO,已提交REDO。
  10. 恢复技术:数据转存(静态:转储期间不允许对数据库存取或修改,动态:转储期间允许对数据库存取或修改),登记日志文件(用来记录事务对数据库更新操作)。
  11. 日志:数据恢复。
  12. 日志文件作用(记录事务对数据库更新的文件):事务故障,系统故障恢复必须用日志文件;动态转储必须建立日志文件;静态转储也可以建立日志文件;
  13. 事务故障恢复:系统自动完成;反向扫描日志文件,更新操作执行逆操作(更新前值写入数据库)如此反复,直到读到事务开始标记;
  14. 系统故障恢复:系统重新启动自动完成;正向扫描日志文件,找出故障发生前已经提交,未完成的事务,分别标记重做和撤销队列。对撤销队列事务执行UNDO:反向扫描,UDO事务执行逆操作(更新前值写入数据库),对重做队列执行REDO:正向扫面日志,更新后值写入数据库。
  15. 介质故障恢复:装入最新数据库后备副本,装入日志文件;重做队列中所有事物进行重做:正向扫面,更新后值写入数据库+DBA介入
  16. 检查点恢复技术:增加检查点记录(建立检查点时刻所有正在执行的事务,这些事务的最近一个日志记录的地址),优点是改善恢复效率;检查点之前什么都不做,检查点之后到系统故障之前REDO,检查点之后到系统故障之后撤销后UNDO
  17. 数据库镜像:解决介质故障;对关键数据和日志文件镜像,而不是整个数据库。

并发控制

  1. 事务是并发控制的基本单位。
  2. 并发控制三种错误:丢失修改(两个事务同时对同一个数据写操作导致其中一个写操作修改丢失),不可重复读(T1事务读取数据后,T2执行更新操作,使得T1无法再现前一次读取结果),读脏数据(并发事务操作中,一个事务对某一数据执行了写操作而又撤销,别的事务读到修改后错误的数据)
  3. 封锁的类型:
    写锁:T对A加X锁,只有T可以读取修改A,其他事务不能向A加锁,直到T释放
    读锁:T对A加S锁,T可以读但不可以修改A,其他事务只能加S锁,不能加X锁
  4. 一级封锁协议:T修改数据R之前加X锁,直到事务结束释放;防止丢失修改
    二级封锁协议:一级+T读取数据R之前加S锁,读完释放;防止丢失修改,读脏
    三级封锁协议:一级+T修改数据R之前加S锁,直到事务结束释放;防止丢失修改,读脏,不可重复读
  5. 避免活锁:先来先服务
  6. 预防死锁:
    一次封锁法:一次将所有要使用的数据全部加锁
    顺序封锁法:预先对数据对象规定一个封锁顺序,所有事务按这个顺序实施封锁。
  7. 可串行化调度:多个事务的并发执行是正确的,当且仅当其结果与按某一次序串行地执行这些事务的结果相同。
  8. 解决可串行化调度:两端锁协议。
  9. 两端锁协议:
    在任何数据进行读、写操作之前,首先要申请并获得该数据的封锁。
    在释放一个封锁之后,事务不再申请和获得任何其他封锁。
    第一阶段:扩展阶段,可以申请任何锁,但不能释放任何锁。
    第二阶段:收索阶段,可以释放任何锁,但不能申请任何锁。

你可能感兴趣的:(DataBase)