关系数据库概述

数据库是以一种可以从中检索信息的方式存储信息的方法。用最简单的术语来说,关系数据库是一种在具有行和列的表中呈现信息的数据库。从某种意义上说,表是关系的集合,它是相同类型(行)的对象的集合。表中的数据可以根据通用键或概念进行关联,并且从表中检索相关数据的能力是术语关系数据库的基础。数据库 管理 系统(DBMS)处理数据的存储,维护和检索方式。对于关系数据库,关系数据库 管理 系统(RDBMS)执行这些任务。本书中使用的 DBMS 是一个通用术语,其中包括 RDBMS。

Integrity Rules

关系表遵循某些完整性规则,以确保其中包含的数据保持准确并始终可访问。首先,关系表中的行应全部不同。如果存在重复的行,则可能无法解决两个可能的选择中的一个是正确的选择。对于大多数 DBMS,用户可以指定不允许重复的行,如果这样做,则 DBMS 将阻止添加任何与现有行重复的行。

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

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

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

  • Employees表*
Employee_NumberFirst_nameLast_NameDate_of_BirthCar_Number
10001JohnWashington28-Aug-435
10083ArvidSharma24-Nov-54null
10120JonasGinsberg01-Jan-69null
10005FlorenceWojokowski04-Jul-7112
10099SeanWashington21-Sep-66null
10035ElizabethYamaguchi24-Dec-59null

该表的主键通常是员工号,因为保证每个人都不同。 (进行比较时,数字也比字符串 更有效.)也可以使用First_NameLast_Name,因为两者的组合也只能标识示例数据库中的一行。仅使用姓氏是行不通的,因为有两个员工的姓氏为“ Washington”。在这种特殊情况下,名字全都不同,因此可以想象使用该列作为主键,但是最好避免使用可能发生重复的列。如果 Elizabeth Jones 在这家公司找到工作并且主键是First_Name,则 RDBMS 将不允许添加她的名字(如果已指定不允许重复)。因为表中已经有一个伊丽莎白,所以添加第二个伊丽莎白会使主键无用,因为它只能识别一行。请注意,尽管对于此示例,使用First_NameLast_Name是唯一的复合键,但在较大的数据库中可能并非唯一。另请注意,Employees表假定每个员工只能有一辆汽车。

SELECT 语句

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

SELECT语句(也称为查询)用于从表中获取信息。它指定一个或多个列标题,要从中选择的一个或多个表以及一些选择条件。 RDBMS 返回满足规定要求的列条 Object 行。诸如此类的SELECT语句将获取拥有公司汽车的员工的名字和姓氏:

SELECT First_Name, Last_Name
FROM Employees
WHERE Car_Number IS NOT NULL

结果集(满足Car_Number列中不包含 null 的要求的行集)如下。因为SELECT语句(第一行)指定了First_NameLast_Name列,所以满足要求的每一行都会打印出名字和姓氏。 FROM子句(第二行)提供了从中选择列的表。

FIRST_NAMELAST_NAME
JohnWashington
FlorenceWojokowski

下面的代码生成的结果集包含整个表,因为它要求无限制(没有WHERE子句)的表 employees 中的所有列。请注意,SELECT *表示“ SELECT所有列”。

SELECT *
FROM Employees

WHERE Clauses

SELECT语句中的WHERE子句提供了选择值的条件。例如,在以下代码段中,仅当值出现在列Last_Name以字符串“华盛顿”开头的行中时,才选择值。

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

关键字LIKE用于比较字符串,它具有可以使用包含通配符的 Pattern 的功能。例如,在上面的代码片段中,“华盛顿”的末尾有一个百分号(%),表示任何包含字符串“华盛顿”加上零个或多个其他字符的值都将满足此选择条件。因此,“华盛顿”或“华盛顿”将是匹配项,但“洗涤”将不是匹配项。 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子句是一种特殊的类型,它涉及联接,下一节将对此进行说明。

Joins

关系数据库的一个显着 Feature 是,可以从称为联接的多个表中获取数据。假设在检索了拥有公司汽车的雇员的姓名之后,一个人想要找出谁拥有哪辆汽车,包括车牌号,里程和车龄。此信息存储在另一个表Cars中:

  • Cars表*
Car_NumberLicense_PlateMileageYear
5ABC12350001996
12DEF12375001999

两个表中必须存在一列,以便将它们彼此关联。该列必须是一个表中的主键,在另一表中称为外键。在这种情况下,出现在两个表中的列是Car_Number,这是表Cars的主键和表Employees的外键。如果 1996 年车牌号为 ABC123 的汽车被撞毁并从Cars表中删除,则也必须从Employees表中删除Car_Number 5,以保持所谓的参照完整性。否则,Employees表中的外键列(Car_Number)将包含一个未引用Cars表中任何内容的条目。外键必须为 null 或等于它所引用表的现有主键值。这不同于主键,主键不能为空。表EmployeesCar_Number列中有几个空值,因为员工可能没有公司的车。

以下代码要求拥有公司汽车的雇员的名字和姓氏,以及这些汽车的车牌号,里程和年份。请注意,FROM子句同时列出了EmployeesCars表,因为请求的数据都包含在两个表中。使用表名和列名前的点(.)指示哪个表包含该列。

SELECT Employees.First_Name, Employees.Last_Name,
    Cars.License_Plate, Cars.Mileage, Cars.Year
FROM Employees, Cars
WHERE Employees.Car_Number = Cars.Car_Number

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

FIRST_NAMELAST_NAMELICENSE_PLATEMILEAGEYEAR
JohnWashingtonABC12350001996
FlorenceWojokowskiDEF12375001999

常用 SQL 命令

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

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

  • SELECT —用于查询和显示数据库中的数据。 SELECT语句指定要包含在结果集中的列。应用程序中使用的绝大多数 SQL 命令都是SELECT语句。

  • INSERT —将新行添加到表中。 INSERT用于填充新创建的表或向现有表添加新的一行。

  • DELETE —从表中删除指定的一行或一组行

  • UPDATE —更改表中一列或一组列中的现有值

更常见的 DDL 命令如下:

  • CREATE TABLE —使用用户提供的列名创建一个表。用户还需要为每一列中的数据指定一种类型。数据类型从一个 RDBMS 到另一个 RDBMS,所以用户可能需要使用元数据来构建特定数据库使用的数据类型。通常,CREATE TABLE的使用频率比数据操作命令要少,这是因为表仅创建一次,而添加或删除行或更改单个值通常会更频繁地发生。

  • DROP TABLE —删除所有行,并从数据库中删除表定义。需要一个 JDBC API 实现来支持 SQL92 过渡级别所指定的 DROP TABLE 命令。但是,对DROP TABLECASCADERESTRICT选项的支持是可选的。此外,当定义了引用要删除的表的视图或完整性约束时,DROP TABLE的行为由实现定义。

  • ALTER TABLE —从表中添加或删除列。它还添加或删除表约束并更改列属性

结果集和游标

满足查询条件的行称为结果集。结果集中返回的行数可以为零,一或很多。用户可以一次访问一行结果集中的数据,而游标提供了这样做的手段。游标可被视为指向包含结果集各行的文件的指针,并且该指针具有跟踪当前正在访问的行的能力。游标允许用户从上到下处理结果集的每一行,因此可以用于迭代处理。大多数 DBMS 在生成结果集时会自动创建一个游标。

较早的 JDBC API 版本为结果集的游标添加了新功能,从而使其可以向前和向后移动,还可以将其移动到指定的行或位置相对于另一行的行。

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

Transactions

当一个用户访问数据库中的数据时,另一用户可能同时访问同一数据。例如,如果第一位用户正在同时更新表中的某些列,而第二位用户正在从同一表中选择列,则第二位用户有可能获得部分旧数据和部分更新数据。因此,DBMS 使用事务将数据维持在一致状态(数据一致性),同时允许多个用户同时访问数据库(数据并发)。

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

锁是一种机制,它禁止两个事务同时处理相同的数据。例如,如果表锁上有未提交的事务,则表锁可防止该表被删除。在某些 DBMS 中,表锁还锁定表中的所有行。行锁可防止两个事务修改同一行,或者防止一个事务选择一行而另一事务仍在修改它。

有关更多信息,请参见Using Transactions

Stored Procedures

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

Metadata

数据库存储用户数据,并且它们还存储有关数据库本身的信息。大多数 DBMS 都有一组系统表,这些系统表列出了数据库中的表,每个表中的列名,主键,外键,存储过程等。每个 DBMS 都有其自己的功能来获取有关表布局和数据库功能的信息。 JDBC 提供了interfaceDatabaseMetaData,驱动程序编写者必须实现该interfaceDatabaseMetaData,以便其方法返回有关驱动程序和/或为其编写驱动程序的 DBMS 的信息。例如,大量方法返回驱动程序是否支持特定功能。该interface为用户和工具提供了一种获取元数据的标准化方法。通常,编写工具和驱动程序的开发人员最可能与元数据有关。