SQL基础-连接表

12 联接表

12.1 理解联接

SQL最强大的特性之一是能够在数据检索查询中动态地联接表。连接是使用SQL SELECT可以执行的最重要的操作之一,对连接和连接语法的良好理解是学习SQL极为重要的一部分。

在您可以有效地使用连接之前,您必须了解关系表和关系数据库设计的基础知识。下面的内容绝不是对这个主题的完整介绍,但应该足以让您开始工作。

理解相关联的表

理解关系表的最佳方法是查看一个真实的示例。
假设您有一个数据库表,其中包含一个产品目录,每个目录项都在自己的行中。您将与每个项目一起存储的信息类型将包括产品描述和价格,以及关于创建产品的公司的供应商信息。
现在假设您有多个由同一供应商创建的目录项。您将在何处存储供应商信息(如供应商名称、地址和联系信息)?您不希望将这些数据与产品一起存储,原因如下:

  • 因为厂商信息对于厂商生产的每个产品都是一样的,所以重复每个产品的信息是浪费时间和存储空间。
  • 如果供应商信息更改(例如,如果供应商移动或其区号更改),则需要更新供应商信息的每次出现。
  • 当数据重复时(即每个产品都使用供应商信息),很可能每次输入的数据都不完全相同。在报告中使用不一致的数据非常困难。

这里的关键是,多次出现相同的数据从来都不是一件好事,这个原则是关系数据库设计的基础。设计关系表是为了将信息分成多个表,每个表对应一个数据类型。这些表通过公共值相互关联(因此关系设计中的关系)。

在我们的示例中,您可以创建两个表,一个用于供应商信息,另一个用于产品信息。Vendors表包含所有供应商信息,每个供应商一个表行,以及每个供应商的唯一标识符。这个值称为主键,可以是供应商ID,也可以是任何其他惟一的值。

Products表只存储产品信息,除了vendor ID (Vendors表的主键)之外没有特定于供应商的信息。此键将Vendors表与Products表联系起来,使用此vendor ID可以使用Vendors表查找有关适当供应商的详细信息。

这对你有什么用?那么,考虑以下几点:

  • 供应商信息不会重复,因此不会浪费时间和空间
  • 如果供应商信息发生更改,您可以更新单个记录,即厂商表。相关表中的数据不变
  • 由于没有重复的数据,所使用的数据显然是一致的,使得数据报告和操作更加简单。
    最重要的是,关系数据可以有效地存储并易于操作。因此,关系数据库的伸缩性比非关系数据库好得多。

Scale
能够处理不断增加的负载而不会失败。一个设计良好的数据库或应用程序可以很好地扩展。

为什么使用联接

如前所述,将数据拆分为多个表可以实现更高效的存储、更容易的操作和更大的可伸缩性。但这些好处是有代价的。

如果数据存储在多个表中,如何使用单个表检索该数据SELECT语句?
答案是使用联接。简单地说,联接是一种用于在SELECT语句中关联表的机制(因此也就是名称联接)。使用一种特殊的语法,可以联接多个表,从而返回一组输出,并且联接可以动态地关联每个表中的正确行。

创建联接

创建联接非常简单。必须指定要包含的所有表以及它们之间的关系。请看下面的例子:

SELECT vend_name, prod_name, prod_price
FROM Vendors, Products
WHERE Vendors.vend_id = Products.vend_id;

让我们看一下前面的代码。SELECT语句通过指定要检索的列,以与到目前为止看到的所有语句相同的方式开始。这里的主要区别是,两个指定列(prod_name和prod_price)在一个表中,而另一个列(vend_name)在另一个表中。

现在看看FROM子句。与前面的所有SELECT语句不同,这个SELECT语句有两个表,分别列在FROM子句、Vendors和Products中。这是在这个SELECT语句中联接的两个表的名称。这些表通过WHERE子句正确地连接,该子句指示DBMS将Vendors表中的vend_id与Products表中的vend_id匹配。

您将注意到这些列被指定为供应商。vend_id和
Products.vend_id。这里需要这个完全限定的列名,因为如果只指定了vend_id, DBMS就无法告诉您所引用的是哪个vend_id列。(有两个,每个表一个。)正如您在前面的输出中看到的,单个SELECT语句返回来自两个不同表的数据。

Fully Qualifying Column Names
如前一课所述,当您可能对所引用的列有歧义时,您必须使用完全限定的列名(表和用句号分隔的列)。如果您引用一个不明确的列名,而没有使用表名完全限定它,那么大多数dbms将返回一条错误消息。

WHERE字句的重要性

使用WHERE子句来设置连接关系可能看起来很奇怪,但实际上,这样做有一个很好的理由。请记住,在SELECT语句中联接表时,这种关系是动态构建的。数据库表定义中没有任何内容可以指导DBMS如何连接这些表。你必须自己去做。当连接两个表时,实际上要做的是将第一个表中的每一行与第二个表中的每一行配对。WHERE子句充当筛选器,只包含与指定筛选条件匹配的行—联接。
如果没有WHERE子句,第一个表中的每一行都将与第二个表中的每一行配对,不管它们在逻辑上是否匹配。

笛卡儿积
没有连接条件的表关系返回的结果。 检索到的行数将是第一个表中的行数乘以第二个表中的行数。

别忘了WHERE子句
确保所有的连接都有WHERE子句,否则DBMS返回的数据会比您想要的多得多。同样,确保WHERE子句是正确的。不正确的筛选条件将导致DBMS返回不正确的数据。有时您会听到返回笛卡尔积的连接类型称为交叉连接。

12.2 链接的类型

12.2.1 内连接

到目前为止使用的连接称为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子句。使用这种语法时,连接条件是使用特殊的ON子句而不是WHERE子句指定的。传递给ON的实际条件与传递给WHERE的实际条件相同。
请参阅DBMS文档,以了解哪种语法是首选的。

根据ANSI SQL规范,内部连接语法的使用优于前面使用的简单等连接语法。的确,SQL纯粹主义者往往对简单语法不屑一顾。也就是说,dbms确实既支持简单格式,也支持标准格式,所以我的建议是您花时间来理解这两种格式,但是使用您觉得更舒服的格式。

12.2.2 联接多个表

SQL不限制可以在SELECT语句中连接的表的数量。创建联接的基本规则保持不变。首先列出所有表,然后定义每个表之间的关系。

性能方面的考虑
DBMSs进程在运行时连接指定的每个表。这个过程可能会非常消耗资源,所以要小心不要不必要地连接表。加入的表越多,性能下降的也就越多。

联接中表的最大数目
虽然SQL本身对每个连接没有最大的表数限制,但是许多dbms确实有限制。如果有限制,请参考DBMS文档来确定有哪些限制。

实验是值得的
正如您所看到的,通常有不止一种方法来执行任何给定的操作SQL操作。很少有明确的对错之分。操作的类型、使用的DBMS、表中的数据量、是否存在索引和键以及大量其他条件都可能影响性能。因此,尝试不同的选择机制来找到最适合你的方法通常是值得的。

12.3 自连接

如前所述,使用表别名的主要原因之一是能够在单个SELECT语句中多次引用同一个表。一个示例将演示这一点。
假设您想向Jim Jones工作的同一家公司的所有客户联系人发送邮件。这个查询要求您首先找出Jim Jones为哪家公司工作,然后找出哪家客户为该公司工作。以下是解决这个问题的一种方法:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值