Java面试 第 6 章 数据库原理

6.1 SQL 语言的功能有哪些

SQL 是结构化查询语言(Structured Query Language)的缩写。

基本的 SQL 语句有 select、insert、update、delete、create、drop、grant、revoke 等。其具体使用方式见表 6-1。

Java面试 第 6 章 数据库原理

例如,设教务管理系统中有 3 个基本表:

学生信息表 S(SNO,SNAME,AGE,SEX),其属性分别表示学号、学生姓名、年龄和性别。

选课信息表 SC(SNO,CNO,SCGRADE),其属性分别表示学号、课程号和成绩。

课程信息表 C(CNO,CNAME,CTEACHER),其属性分别表示课程号、课程名称和任课老师姓名。

Java面试 第 6 章 数据库原理Java面试 第 6 章 数据库原理

Java面试 第 6 章 数据库原理

4)找出没有选修过何昊老师的课程的所有学生的姓名。

Java面试 第 6 章 数据库原理

5)列出有两门以上(含两门)不及格课程(成绩小于 60)的学生的姓名及其平均成绩。

Java面试 第 6 章 数据库原理

Java面试 第 6 章 数据库原理Java面试 第 6 章 数据库原理

Java面试 第 6 章 数据库原理


引申:delete 与 truncate 命令有哪些区别?

相同点:都可以用来删除一个表中的数据。

不同点:

1)truncate 是一个数据定义语言(Data Definition Language,DDL),它会被隐式地提交,一旦执行后将不能回滚。delete 执行的过程是每次从表中删除一行数据,同时将删除的操作以日志的形式进行保存,以便将来进行回滚操作。

2)用 delete 操作后,被删除的数据占用的存储空间还在,还可以恢复。而用 truncate 操作删除数据后,被删除的数据会立即释放占用的存储空间,被删除的数据是不能被恢复的。

3)truncate 的执行速度比 delete 快。

参考资料:drop、delete和truncate的区别

drop和truncate操作立即生效;delete操作在事务提交之后才生效。若要删除部分数据,应该使用delete,并带上where子句。


6.2 内连接与外连接有什么区别

内连接,只有两个表相匹配的行才能在结果集中出现。返回的结果集选取了两个表中所有相匹配的数据,舍弃了不匹配的数据。由于内连接是从结果表中删除与其他连接表中没有匹配的所有行,所以内连接可能会造成信息的丢失。内连接的语法如下:

select fieldlist from table1[inner]join table2 on table1.column=table2.column

内连接是保证两个表中的所有行都满足连接条件,而外连接则不然。外连接不仅包含符合连接条件的行,而且还包括左表(左外连接时)、右表(右外连接时)或两个边接表(全外连接)中的所有数据行。SQL 的外连接共有 3 种类型:左外连接(关键字为 LEFT OUTER JOIN)、右外连接(关键字为 RIGHT OUTER JOIN)和全外连接(关键字为 FULL OUTER JOIN)。外连接的用法和内连接一样,只是将 INNER JOIN 关键字替换为相应的外连接关键字即可。

内连接只显示符合连接条件的记录,外连接除了显示符合连接条件的记录外,还显示表中的记录,例如,如果使用左外连接,还显示左表中的记录。


6.3 什么是事务

事务是数据库中一个单独的执行单元(Unit),它通常由高级数据库操作语言(例如 SQL)或编程语言(例如 C++、Java 等)编写的用户程序的执行所引起。当在数据库中更改数据成功时,在事务中更改的数据便会提交,不再改变。否则,事务就取消或者回滚,更改无效。

事务必须满足 4 个属性,即原子性(atomicity)、一致性(consistency)、隔离性(isola-tion)、持久性(durability),即 ACID 4 种属性。

(1)原子性

事务是一个不可分割的整体,为了保证事务的总体目标,事务必须具有原子性,即当数据修改时,要么全执行,要么全不执行,即不允许事务部分地完成,避免了只执行这些操作的一部分而带来的错误。原子性要求事务必须被完整执行。

(2)一致性

一个事务执行之前和执行之后,数据库数据必须保持一致性状态。数据库的一致性状态应该满足模式锁指定的约束,那么在完整执行该事务后数据库仍然处于一致性状态。为了维护所有数据的完整性,在关系型数据库中,所有规则必须应用到事务的修改上。数据库的一致性状态由用户来负责,由并发控制机制实现,例如银行转账,转账前后两个账户金额之和应保持不变。由于并发操作带来的数据不一致性包括丢失数据修改、读「脏」数据、不可重复读和产生「幽灵」数据。

(3)隔离性

隔离性也被称为独立性,当两个或多个事务并发执行时,为了保证数据的安全性,将一个事物内部的操作与事务的操作隔离起来,不被其他正在进行的事务看到,例如,对任何一对事务 T1 和 T2,对 T1 而言,T2 要么在 T1 开始之前已经结束,要么在 T1 完成之后再开始执行。数据库有 4 种类型的事务隔离级别:不提交的读、提交的读、可重复的读和串行化。因为隔离性使得每个事务的更新在它被提交之前,对其他事务都是不可见的,所以,实现隔离性是解决临时更新与消除级联回滚问题的一种方式。

(4)持久性

持久性也被称为永久性,事务完成以后,DBMS 保证它对数据库中的数据的修改是永久性的,当系统或介质发生故障时,该修改也永久保持。持久性一般通过数据库备份与恢复来保证。

一般情况下,通过执行 COMMIT 或 ROLLBACK 语句来终止事务,当执行 COMMIT 语句时,自事务启动以来对数据库所做的一切更改就成为永久性的了,即被写入磁盘;而当执行 ROLLBACK 语句时,自事务启动以来对数据库所做的一切更改都会被撤销,并且数据库中内容返回到事务开始之前所处的状态。无论什么情况,在事务完成时,都能保证回到一致状态。


6.4 什么是存储过程?它与函数有什么区别与联系

SQL 语句在执行时要先编译,然后再被执行。在大型数据库系统中,为了提高效率,将为了完成特定功能的 SQL 语句集进行编译优化后,存储在数据库服务器中,用户通过指定存储过程的名字来调用执行

下面为一个创建存储过程的常用语法。

Java面试 第 6 章 数据库原理

使用存储过程可以增强 SQL 语言的功能和灵活性,由于可以用流程控制语句编写存储过程,有很强的灵活性,因此可以完成复杂的判断和运算,并且可以保证数据的安全性和完整性。同时,存储过程可以使没有权限的用户在控制之下间接地存取数据库,也保证了数据的安全。

需要注意的是,存储过程不等于函数,二者虽然本质上没有区别,但还是有如下几个方面的不同:

1)存储过程一般是作为一个独立的部分来执行,而函数可以作为查询语句的一个部分来调用。由于函数可以返回一个对象,因此它可以在查询语句中位于 From 关键字的后面。

2)一般而言,存储过程实现的功能较复杂,而函数实现的功能针对性较强。

3)函数需要用括号包住输入的参数,且只能返回一个值或表对象,而存储过程可以返回多个参数

4)函数可以嵌入在 SQL 中使用,可以在 select 中调用,存储过程则不行。

5)函数不能直接操作实体表,只能操作内建表。

6)存储过程在创建时即在服务器上进行了编译,其执行速度比函数快。


6.5 各种范式有什么区别

在设计与操作维护数据库时,最关键的问题就是要确保数据能够正确地分布到数据库的表中。使用正确的数据结构,不仅有助于对数据库进行相应的存取操作,还可以极大地简化应用程序中的其他内容(查询、窗体、报表、代码等),按照「数据库规范化」对表进行设计,其目的就是减少数据库中的数据冗余,以增加数据的一致性。

范化是在识别数据库中的数据元素、关系以及定义所需的表和各表中的项目这些初始工作之后的一个细化的过程。常见的范式有 1NF、2NF、3NF、BCNF 以及 4NF。

Java面试 第 6 章 数据库原理

6.6 什么是触发器

触发器是一种特殊类型的存储过程,它由事件触发,而不是程序调用或手工启动,当数据库有特殊的操作时,这些操作由数据库中的事件来触发,自动完成这些 SQL 语句。使用触发器可以用来保证数据的有效性和完整性,完成比约束更复杂的数据约束。

Java面试 第 6 章 数据库原理

根据 SQL 语句的不同,触发器可分为 DML 触发器和 DLL 触发器。

DML 触发器是当数据库服务器发生数据操作语言事件时执行的存储过程,有 After 和 In-stead Of 这两种触发器。After 触发器被**触发是在记录改变之后进行的一种触发器。Instead Of 触发器是在记录变更之前,去执行触发器本身所定义的操作,而不是执行原来 SQL 语句里的操作。DLL 触发器是在响应数据定义语言事件时执行的存储过程。

触发器的主要作用表现为以下几个方面:

1)增加安全性。

2)利用触发器记录所进行的修改以及相关信息,跟踪用户对数据库的操作,实现审计。

3)维护那些通过创建表时的声明约束不可能实现的复杂的完整性约束以及对数据库中特定事件进行监控与响应。

4)实现复杂的非标准的数据库相关完整性规则、同步实时地复制表中的数据。

5)触发器是自动的,它们在对表的数据做了任何修改之后就会被**,例如可以自动计算数据值,若数据的值达到了一定的要求,则进行特定的处理。以某企业财务管理为例,如果企业的资金出现短缺,并且达到某种程度时,则会发送警告信息。

引申:触发器分为事前触发和事后触发,这两者有什么区别?语句级触发和行级触发有什么区别?

事前触发发生在事件发生之前,用于验证一些条件或进行一些准备工作;事后触发发生在事件发生之后,做收尾工作。事前触发可以获得之前和新的字段值,而事后触发可以保证事务的完整性。语句级触发可以在语句执行之前或之后执行,而行级触发在触发器所影响的每一行触发一次。

6.7 什么是游标

数据库中,游标提供了一种对从表中检索出的数据进行操作的灵活手段,它实际上是一种能从包含多条数据记录的结果集中每次提取一条记录的机制。

游标总是与一条 SQL 选择语句相关联,因为游标是由结果集(可以是零条、一条或由相关的选择语句检索出的多条记录)和结果集中指向特定记录的游标位置组成的。当决定对结果集进行处理时,必须声明一个指向该结果集的游标。

游标允许应用程序对查询语句 select 返回的行结果集中的每一行进行相同或不同的操作,而不是一次对整个结果集进行同一种操作;它还提供对基于游标位置而对表中数据进行删除或更新的功能;游标还把作为面向集合的数据库管理系统和面向行的程序设计连接了起来,使两种数据处理方式能够进行「沟通」。

Java面试 第 6 章 数据库原理

在 select 返回的行集合中,游标不允许程序对整个行集合执行相同的操作,但对每一行数据的操作不作要求。

游标有以下两个优点:

1)在使用游标的表中,对行提供删除和更新的功能。

2)游标将面向集合的数据库管理系统和面向行的程序设计连接了起来。

6.8 如果数据库日志满了,会出现什么情况

日志文件(Log File)记录所有对数据库数据的修改,主要是保护数据库以防故障发生,以及恢复数据时使用。其特点如下:

1)每一个数据库至少包含两个日志文件组。每个日志文件组至少包含两个日志文件成员。

2)日志文件组以循环方式进行写操作。

3)每一个日志文件成员对应一个物理文件。

通过日志文件来记录数据库事务可以最大限度地保证数据的一致性与安全性,但一旦数据库中日志满了,就只能执行查询等读操作,不能执行更改、备份等操作,原因是任何写操作都要记录日志,也就是说,基本上处于不能使用的状态。

6.9 union 和 union all 有什么区别

union 在进行表求并集后会去掉重复的元素,所以会对所产生的结果集进行排序运算,删除重复的记录再返回结果。

union all 则只是简单地将两个结果集合并后就返回结果。因此,如果返回的两个结果集中有重复的数据,那么返回的结果集就会包含重复的数据。

从上面的对比可以看出,在执行查询操作时,union all 要比 union 快很多,所以,如果可以确认合并的两个结果集中不包含重复的数据,那么最好使用 union all,

例如,现有两个学生表 Table 1(见表 6-7)和 Table 2(见表 6-8)。

Java面试 第 6 章 数据库原理

select∗from Table1 union select∗from Table2 的查询结果见表 6-9:

select∗from Table1 union all select∗from Table2 的查询结果见表 6-10:

6.10 什么是视图

视图是由从数据库的基本表中选取出来的数据组成的逻辑窗口,与基本表不同,它是一个虚表。在数据库中,存放的只是视图的定义,而不存放视图包含的数据项,这些项目仍然存放在原来的基本表结构中。

视图的作用主要有以下几点:首先,可以简化数据查询语句;其次,可以使用户能从多角度看待同一数据;然后,通过引入视图可以提高数据的安全性;最后,视图提供了一定程度的逻辑独立性等。

通过引入视图机制,用户可以将注意力集中在其关心的数据上(而非全部数据),这样就大大提高了用户效率与用户满意度,而且如果这些数据来源于多个基本表结构,或者数据不仅来自于基本表结构,还有一部分数据来源于其他视图,并且搜索条件又比较复杂时,需要编写的查询语句就会比较烦琐,此时定义视图就可以使数据的查询语句变得简单可行。定义视图可以将表与表之间的复杂的操作连接和搜索条件对用户不可见,用户只需要简单地对一个视图进行查询即可,故增加了数据的安全性,但不能提高查询的效率。

======================================================

end