《SQL必知必会》--联结表

联结表

这一课还是跨表操作,我们上一节课讲的是子查询。由于我们的表格在之前就已经为我们设计好,因此,我们不用去思考,为什么我们可以使用子查询?

联结简介

联结表是SQL最强大功能之一。联结是利用SQL的SELECT能执行的最重要的操作。
在理解联结前,必须联结关系表以及关系数据库的一些基础知识。

什么是关系表

关系表的设计就是要把信息分解成多个表,一类数据一个表。各表通过某些共同的值相互关联。
由关系表组成的数据库就是关系数据库咯。

理解关系表,最好看个例子。
有一个包含产品目录的数据库表,其中每类物品占一行。对于每一种物品,要储存的信息包括产品描述、价格,以及生产该产品的供应商。
现在有同一个供应商生产的多种物品,那么在何处储存供应商名、地址、联系方式等供应商信息呢?将这些数据与产品分开的依据是什么?

  • 同一供应商生产的每个产品,其供应商信息都是相同的,对每个产品重复此信息既浪费时间又浪费储存空间;
  • 如果供应商信息发生变化,只需修改一处即可。
  • 如果数据重复则很难保证多次输入该数据的方式都相同。不一致的数据有不可利用。

基于以上原因,我们需要分类将各式各样的信息分别储存在多个表中,但是,每个表又不能完全与其他表不同。具体的关系表设计(基于举例的演示)如下:

在这个例子中,可以建立两个表:一个储存供应商信息,另一个储存产品信息。
Vendors表包含所有供应商信息,每个供应商占一行,具有唯一的标识。此标识键称为主键(primary key),可以是供应商ID或任何其他唯一值。
Products表只储存产品信息,除了储存供应商ID(Vendors表主键)外,不储存其他有关供应商的信息。
Vendors表的主键将两个表关联,利用主键可以在Vendors中找出相应供应商的详细信息。

为什么使用联结

如上所述,将数据分解成多个表能更有效地储存,更方便得处理,并且可伸缩性更好。但是这些好处都是有代价的。

这个代价就是,我们不能一条简单的指令就显示出关于某个产品的所有的详细信息。

那怎么办呢?就是在SELECT()检索数据时,使用联结。

创建联结

创建联结非常简单,指定要联结的所有表以及关联他们的方式即可。请看例子:

1
2
3
select vend_name, prod_name, prod_price
from vendors, products
WHERE products.vend_id = vendors.vend_id;
  • SELECT()指定的三列分处于两表;
  • FROM后不仅跟一个表,而是将涉及的表都写上,表示将要联结的两个表;
  • WHERE语句后跟完全限定列名,指示关联规则。

在前几课已经讲过关于完全限定列的双循环原理,因此,WHERE语句中等号左右两边顺序与位置不重要。
但是,为了规范,以后我还是将具有主键性质的完全限定列名(如vendors.vend_id)放在右边。

内联结

上述联结为等值联结(equijion),也被称为内联结(inner jion)。
上述代码的形似是等值联结们可以换个形式表示相同的命令,返回相同的数据。

1
2
3
select vend_name, prod_name, prod_price
from vendors inner join products
on vendors.vend_id = products.vend_id;

联结多个表

同样按照上述思路来做。

1
2
3
4
select vend_name, prod_name, prod_price, order_num
from vendors, products, orderitems
where vendors.vend_id = products.vend_id and
products.prod_id = orderitems.prod_id;

一开始想要按照内联结的方式来做,但是总是不成功,于是按照这种简单的等值联结,这一尝试,确实不错,简单,易懂。

再展示一个上节课讲子查询时的例子,检索订购产品RGAN01的顾客列表。

1
2
3
4
5
select cust_name, cust_contact
from customers, orders, orderitems
where customers.cust_id = orders.cust_id
and orders.order_num = orderitems.order_num
and prod_id = 'RGAN01';

这里多了一个过滤条件prod_id = 'RGAN01',理解为,前两个WHERE指令关联表中所有信息,最后一条指令过滤具体信息。

小结

在实际中,细分表列是常见的。因此,跨表操作必须熟悉。

本课,讲的只是一种常见的简单的联结形式,想一想,有没有其他形式的联结呢?