SQL最强大的功能之一就是能在数据检索查询的执行中联结(join)表。 联结是利用SQL的SELECT能执行的最重要的操作,很好地理解联结及其语法是学习SQL的一个极为重要的组成部分。
关系表的设计要保证把信息分解成多个表,一类数据一个表。各表通过某些常用的值(即关系设计中的关系(relational))互相关联。
外键(foreign key) 外键为某个表中的一列,它包含另一个表的主键值,定义了两个表之间的关系。
可伸缩性(scale) 能够适应不断增加的工作量而不失败。设计良好的数据库或应用程序称之为可伸缩性好(scale well)。
分解数据为多个表能更有效地存储,更方便地处理,并且具有更大的可伸缩性。但这些好处是有代价的。
如果数据存储在多个表中,怎样用单条SELECT语句检索出数据?
答案是使用联结。简单地说,联结是一种机制,用来在一条SELECT语句中关联表,因此称之为联结。使用特殊的语法,可以联结多个表返回一组输出,联结在运行时关联表中正确的行。
联结的创建非常简单,规定要联结的所有表以及它们如何关联即可。请看下面的例子:
select vend_name,prod_name,prod_price
from vendors,products
where vendors.vend_id = products.vend_id
order by vend_name,prod_name;
利用WHERE子句建立联结关系似乎有点奇怪,但实际上,有一个很充分的理由。请记住,在一条SELECT语句中联结几个表时,相应的关系是在运行中构造的。在数据库表的定义中不存在能指示MySQL如何对表进行联结的东西。你必须自己做这件事情。在联结两个表时,你实际上做的是将第一个表中的每一行与第二个表中的每一行配对。WHERE子句作为过滤条件,它只包含那些匹配给定条件(这里是联结条件)的行。 没有WHERE子句,第一个表中的每个行将与第二个表中的每个行配对,而不管它们逻辑上是否可以配在一起。
目前为止所用的联结称为等值联结(equijoin),它基于两个表之间的相等测试。这种联结也称为内部联结。其实,对于这种联结可以使用稍微不同的语法来明确指定联结的类型。下面的SELECT语句返回与前面例子完全相同的数据:
select vend_name,prod_name,prod_price
from vendors inner join products
on vendors.vend_id = products.vend_id;
此语句中的SELECT与前面的SELECT语句相同,但FROM子句不同。这里, 两个表之间的关系是FROM子句的组成部分,以INNER JOIN指定。在使用这种语法时,联结条件用特定的ON子句而不是WHERE子句给出。传递给ON的实际条件与传递给WHERE的相同。
使用子查询执行复杂的SELECT语句返回订购产品TNT2的客户列表:
select cust_name,cust_contact from customers
where cust_id in (select cust_id from orders
where order_num in ( select order_num from orderitems
where prod_id = 'TNT2'));
下面是使用联结的相同查询:
select cust_name,cust_contact
from customers,orders,orderitems
where customers.cust_id = orders.cust_id
and orderitems.order_num = orders.ordes.order_num
and prod_id = 'TNT2";
这个查询中返回数据需要使用3个表。但这里我们没有在嵌套子查询中使用它们,而是使用了两个联结。这里有3个WHERE子句条件。前两个关联联结中的表,后一个过滤产品TNT2的数据。