本文介绍什么是联结,为什么使用联结,以及如何编写使用联结的SELECT语句。
1. 联结
SQL最强大的功能之一就是能在数据查询的执行中联结(join)表。联结是SQL的SELECT能执行的最重要的操作,理解联结及其语法是学习SQL的重要部分。要有效使用联结,首先需要了解关系表及关系数据库设计的一些基础知识。下面的介绍是入门级的内容,足以帮助理解联结的基本概念。
1.1 关系表
理解关系表,最好通过一个例子来说明。假设有一个包含产品目录的数据库表,每一类物品占一行。对于每种物品,要存储的信息包括产品描述、价格和生产该产品的供应商信息。如果同一供应商生产了多种物品,那么如何存储供应商的名称、地址、联系方式等信息呢?将这些数据与产品信息分开存储的理由有以下几点:
- 同一供应商生产的每个产品,其供应商信息是相同的,若对每个产品重复存储这些信息,不仅浪费时间,也浪费存储空间;
- 如果供应商信息发生变化,例如供应商的地址或电话号码变动,更新一次即可,无需更新所有产品数据;
- 如果供应商信息重复存储,会导致数据一致性问题,不同的输入方式可能造成数据不一致,影响后续分析和报表。
关键在于,相同的数据出现多次是低效的,这是关系数据库设计的基础。关系表的设计应将信息分解成多个表,每类数据存一个表,通过某些共同的值将各表关联(因此称为关系数据库)。
在这个例子中,可以建立两个表:一个存储供应商信息,另一个存储产品信息。Vendors
表包含所有供应商信息,每个供应商占一行,且具有唯一标识(主键,primary key)。Products
表仅存储产品信息,除了存储供应商ID外,不存储其他供应商信息。通过供应商ID,Products
表与 Vendors
表关联,可以从 Vendors
表中查询到相关供应商的详细信息。
这样做的好处包括:
- 供应商信息不重复,节省存储空间;
- 如果供应商信息发生变动,只需在
Vendors
表中更新一次,其他表中的数据无需更改; - 数据一致性更好,便于数据处理和报表生成。
总之,关系数据库能有效存储数据,并方便后续处理,因此,其可伸缩性要优于非关系数据库。
1.2 为什么使用联结
如前所述,将数据分解为多个表可以更高效地存储数据,且更便于管理,但这也带来了挑战:如何用一条SELECT语句从多个表中检索数据?答案是使用联结。联结是一种机制,可以在一条SELECT语句中将多个表关联,返回关联后的数据集。联结在执行时会根据特定条件把表中的行匹配在一起。
2. 创建联结
创建联结非常简单,只需要指定要联结的所有表和它们的关联条件。以下是一个例子:
SELECT vend_name, prod_name, prod_price
FROM Vendors, Products
WHERE Vendors.vend_id = Products.vend_id;
输出结果
分析:这段代码与前面所写的SELECT语句类似,指定了需要检索的列。不同之处在于,这里列出了两个表:Vendors
和 Products
。在 FROM
子句中,指定了这两个表,表示要联结的表。然后在 WHERE
子句中,通过条件 Vendors.vend_id = Products.vend_id
,将两个表中的行关联起来。
注意,在联结中需要明确列名的表名,如 Vendors.vend_id
和 Products.vend_id
,因为每个表都有一个 vend_id
列,否则数据库系统会无法知道你是指哪个表的列。
2.1 WHERE子句的重要性
使用 WHERE
子句来建立联结关系,可能有些令人困惑,但这是有充分理由的。实际上,表之间的关系是在查询执行时动态构造的,数据库表的定义中并没有指定如何联结表。在联结两个表时,数据库会将第一个表中的每一行与第二个表中的每一行配对,WHERE
子句则作为过滤条件,确保只有那些满足联结条件的行才会被返回。如果没有 WHERE
子句,数据库将进行笛卡尔积计算,即第一个表的每一行将与第二个表的每一行配对,可能会返回大量无意义的结果。
笛卡儿积(Cartesian Product)
没有联结条件的查询会返回笛卡尔积,结果行数等于第一个表的行数乘以第二个表的行数。以下示例会展示这一点:
SELECT vend_name, prod_name, prod_price
FROM Vendors, Products;
输出结果
从输出中可以看到,这个查询返回的是笛卡尔积,这意味着每个供应商都会与每个产品匹配,显然这不是我们想要的结果。为了避免这种情况,必须确保在联结查询中正确使用 WHERE
子句。
2.2 内联结
到目前为止,我们使用的联结是等值联结(equijoin),它基于两个表之间的相等测试,也叫做内联结(inner join)。这种联结也可以使用另一种语法来明确指定联结类型,语法如下:
SELECT vend_name, prod_name, prod_price
FROM Vendors
INNER JOIN Products ON Vendors.vend_id = Products.vend_id;
分析:此语句的 SELECT
部分与之前相同,但 FROM
子句有所不同。这里,使用了 INNER JOIN
来明确指定两个表之间的关系,并通过 ON
子句来指定联结条件。ON
子句中的条件与 WHERE
子句中的条件是等价的。
说明:“正确的”语法
ANSI SQL标准推荐使用 INNER JOIN
语法,而传统的等值联结语法(如 WHERE
子句方式)则属于较旧的形式。虽然DBMS支持两者,但建议大家理解这两种格式,实际应用时可以根据自己的习惯和需求选择。
总结
SQL联结是强大的查询工具,通过它可以将多个表中的相关数据整合到一起,方便分析和处理。理解关系表设计和联结语法对于高效使用SQL至关重要。联结能够帮助我们优化数据库设计,减少冗余数据,提高存储效率和一致性。在实际使用中,正确使用 WHERE
或 INNER JOIN
子句来指定联结条件,是确保查询结果准确的关键。