文档

Java™教程
隐藏目录
关系数据库概述
导航: JDBC数据库访问
课程: JDBC简介

关系数据库概述

数据库是一种以能够检索信息的方式存储信息的手段。简单来说,关系型数据库是以行和列的形式呈现信息的一种数据库。表在这里被称为关系,因为它是相同类型对象(行)的集合。表中的数据可以根据共同的键或概念进行关联,从表中检索相关数据是关系型数据库这个术语的基础。数据库管理系统(DBMS)处理数据的存储、维护和检索方式。在关系型数据库的情况下,关系型数据库管理系统(RDBMS)执行这些任务。在本书中,DBMS是一个包括RDBMS在内的通用术语。

完整性规则

关系表遵循一定的完整性规则,以确保它们所包含的数据保持准确并始终可访问。首先,关系表中的行应该是唯一的。如果有重复的行,解决哪个是正确选择的问题可能会出现问题。对于大多数DBMS,用户可以指定不允许重复行,如果这样做,DBMS将阻止添加任何重复现有行的行。

传统关系模型的第二个完整性规则是列值不能是重复组或数组。数据完整性的第三个方面涉及到空值的概念。数据库通过使用空值来处理数据可能不可用的情况,表示值缺失。它不等同于空白或零。空白被认为等于另一个空白,零被认为等于另一个零,但两个空值不被认为是相等的。

当表中的每一行都不同时,可以使用一个或多个列来标识特定的行。这个唯一的列或列组被称为主键。任何作为主键的列都不能为null;如果是null,包含它的主键将不再是一个完整的标识符。这个规则被称为实体完整性。

Employees表演示了一些这些关系数据库的概念。它有五列和六行,每一行代表一个不同的员工。

Employees
员工编号 出生日期 汽车编号
10001 Axel Washington 28-Aug-43 5
10083 Arvid Sharma 24-Nov-54 null
10120 Jonas Ginsberg 01-Jan-69 null
10005 Florence Wojokowski 04-Jul-71 12
10099 Sean Washington 21-Sep-66 null
10035 Elizabeth Yamaguchi 24-Dec-59 null

通常情况下,该表的主键通常是员工编号,因为每个员工编号都保证是不同的。(数字与字符串相比,用于比较更高效。)也可以使用First_NameLast_Name,因为这两者的组合也可以唯一标识样例数据库中的一行数据。如果仅使用姓氏将无法起到作用,因为有两个姓氏为“Washington”的员工。在这种特殊情况下,名字都是不同的,所以理论上可以使用该列作为主键,但最好避免使用可能出现重复的列作为主键。如果Elizabeth Yamaguchi在这家公司找到工作并且主键是First_Name,如果已经规定不允许重复,关系数据库管理系统将不允许添加她的名字。因为表中已经有一个Elizabeth,再添加一个将使得主键无法用于唯一标识一行。请注意,尽管在本示例中使用First_NameLast_Name作为唯一的组合主键,但在更大的数据库中可能不是唯一的。还请注意,Employees表假设每个员工只能有一辆汽车。

SELECT语句

SQL是一种设计用于关系数据库的语言。有一组基本的SQL命令被视为标准,并被所有关系数据库管理系统使用。例如,所有关系数据库管理系统都使用SELECT语句。

SELECT语句,也称为查询语句,用于从表中获取信息。它指定一个或多个列标题,一个或多个要选择的表,以及一些选择的条件。关系数据库管理系统返回满足所述要求的列条目的行。以下是一个SELECT语句的示例,将获取具有公司汽车的员工的名字和姓氏:

SELECT First_Name, Last_Name
FROM Employees
WHERE Car_Number IS NOT NULL

结果集(满足Car_Number列不为null的要求的行集)如下所示。对于每一行满足要求的行,将打印出名字和姓氏,因为SELECT语句(第一行)指定了First_NameLast_Name这两列。FROM子句(第二行)给出了将从中选择列的表。

FIRST_NAME LAST_NAME
Axel Washington
Florence Wojokowski

以下代码生成了一个包含整个表的结果集,因为它要求获取表 Employees 中的所有列且没有限制条件(没有 WHERE 子句)。注意,SELECT * 表示“选择所有列”。

SELECT *
FROM Employees

WHERE 子句

SELECT 语句中的 WHERE 子句提供了选择值的条件。例如,在以下代码片段中,只有在包含列 Last_Name 的行中出现字符串 'Washington' 时才会选择值。

SELECT First_Name, Last_Name
FROM Employees
WHERE Last_Name LIKE 'Washington%'

关键字 LIKE 用于比较字符串,并提供了可以使用通配符的功能。例如,在上面的代码片段中,'Washington' 的末尾有一个百分号(%),表示任何包含字符串 'Washington' 加上零个或多个其他字符的值都将满足此选择条件。因此,'Washington' 或 'Washingtonian' 都会匹配,但 'Washing' 不会。LIKE 子句中使用的另一个通配符是下划线(_),它代表任意一个字符。例如:

WHERE Last_Name LIKE 'Ba_man'

将匹配 'Barman'、'Badman'、'Balman'、'Bagman'、'Bamman' 等。

下面的代码片段中的 WHERE 子句使用等号(=)来比较数字。它选择了被分配到汽车 12 的员工的名字和姓氏。

SELECT First_Name, Last_Name
FROM Employees
WHERE Car_Number = 12

下一个代码片段选择了员工编号大于 10005 的员工的名字和姓氏:

SELECT First_Name, Last_Name
FROM Employees
WHERE Employee_Number > 10005

WHERE 子句可以变得相当复杂,包含多个条件,并且在某些 DBMS 中,还可以包含嵌套条件。本概述不涵盖复杂的 WHERE 子句,但以下代码片段具有两个条件的 WHERE 子句;此查询选择了员工编号小于 10100 且没有公司车辆的员工的名字和姓氏。

SELECT First_Name, Last_Name
FROM Employees
WHERE Employee_Number < 10100 and Car_Number IS NULL

特殊类型的 WHERE 子句涉及连接,这将在下一节中解释。

连接

关系数据库的一个显著特点是可以从多个表中获取数据,这称为连接。假设在检索拥有公司车辆的员工姓名后,想要找出谁拥有哪辆车,包括车辆的制造商、型号和年份。这些信息存储在另一个表 Cars 中:

汽车
汽车编号 制造商 型号 年份
5 本田 思域 DX 1996
12 丰田 卡罗拉 1999

这两个表必须有一个相同的列,以便将它们关联起来。这个列在一个表中必须是主键,在另一个表中则称为外键。在这个例子中,出现在两个表中的列是 汽车编号,它是表 汽车 的主键,也是表 员工 的外键。如果1996年的本田思域在 汽车 表中被撞毁并删除,那么 汽车编号 为5的员工也必须从 员工 表中删除,以保持所谓的引用完整性。否则,员工 表中的外键列(汽车编号)将包含一个在 汽车 表中没有对应值的条目。外键必须为空,或等于所引用表的现有主键值。这与主键不同,主键不允许为空。在 员工 表的 汽车编号 列中有几个空值,因为员工可能没有公司车。

下面的代码要求输入有公司车辆的员工的名字和姓氏,以及这些车辆的制造商、型号和年份。请注意,FROM 子句列出了 员工汽车 两个表,因为请求的数据包含在这两个表中。使用表名和点号(.)之前的列名表示该列位于哪个表中。

SELECT Employees.First_Name, Employees.Last_Name,
    Cars.Make, Cars.Model, Cars.Year
FROM Employees, Cars
WHERE Employees.Car_Number = Cars.Car_Number

这将返回一个类似以下的结果集:

名字 姓氏 车牌号 里程数 年份
约翰 华盛顿 ABC123 5000 1996
弗洛伦斯 沃约科夫斯基 DEF123 7500 1999

常用的SQL命令

SQL命令分为多个类别,其中最主要的是数据操作语言(DML)命令和数据定义语言(DDL)命令。DML命令处理数据,可以检索数据或修改数据以保持其最新状态。DDL命令用于创建或更改表和其他数据库对象,例如视图和索引。

以下是常见的DML命令列表:

以下是常见的DDL命令:

结果集和游标

满足查询条件的行称为结果集。结果集返回的行数可以是零、一或多。用户可以逐行访问结果集中的数据,游标提供了这种功能。可以将游标视为指向包含结果集行的文件的指针,并且该指针具有跟踪当前访问的行的能力。游标允许用户从顶部到底部处理结果集的每一行,因此可用于迭代处理。大多数DBMS在生成结果集时会自动创建一个游标。

早期的JDBC API版本为结果集的游标增加了新的功能,使其能够向前和向后移动,还允许它移动到指定的行或相对于另一行的位置。

更多信息请参见从结果集中检索和修改值

事务

当一个用户正在访问数据库中的数据时,另一个用户可能同时访问相同的数据。例如,如果第一个用户在同时更新表中的某些列,而第二个用户在同时从同一张表中选择列,那么第二个用户可能会得到部分旧数据和部分更新数据。因此,DBMS使用事务来保持数据处于一致状态(数据一致性),同时允许多个用户同时访问数据库(数据并发性)。

事务是由一个或多个SQL语句组成的逻辑工作单元。事务以提交(commit)或回滚(rollback)结束,具体取决于数据一致性或数据并发性是否存在问题。提交语句会永久保存事务中SQL语句导致的更改,而回滚语句会撤销事务中SQL语句导致的所有更改。

锁是一种机制,禁止两个事务同时操作相同的数据。例如,表锁会阻止在该表上存在未提交的事务时删除表。在某些DBMS中,表锁还会锁定表中的所有行。行锁会阻止两个事务修改相同的行,或者阻止一个事务在另一个事务修改它时选择该行。

更多信息请参见使用事务

存储过程

存储过程是一组可以按名称调用的SQL语句。换句话说,它是可执行的代码,是一个执行特定任务的小程序,可以像调用函数或方法一样调用它。传统上,存储过程是用DBMS特定的编程语言编写的。最新一代的数据库产品允许使用Java编程语言和JDBC API编写存储过程。用Java编程语言编写的存储过程在DBMS之间是字节码可移植的。一旦编写了存储过程,它可以被使用和重复使用,因为支持存储过程的DBMS会将其存储在数据库中,正如其名称所暗示的那样。有关编写存储过程的信息,请参见使用存储过程

元数据

数据库存储用户数据,也存储有关数据库本身的信息。大多数DBMS都有一组系统表,列出数据库中的表,每个表中的列名,主键,外键,存储过程等等。每个DBMS都有自己的函数来获取有关表格布局和数据库特性的信息。JDBC提供了接口DatabaseMetaData,驱动程序编写者必须实现这个接口,以便它的方法返回有关驱动程序和/或DBMS的信息。例如,许多方法返回驱动程序是否支持特定功能。这个接口给用户和工具提供了一种标准化的方式来获取元数据。一般来说,编写工具和驱动程序的开发人员最有可能关注元数据。


上一页: JDBC体系结构
下一页: JDBC基础知识