联接基础知识

通过联接,可以从两个或多个表中根据各个表之间的逻辑关系来检索数据。联接指明了 MicrosoftSQL Server 应如何使用一个表中的数据来选择另一个表中的行。

联接条件可通过以下方式定义两个表在查询中的关联方式:

  • 指定每个表中要用于联接的列。典型的联接条件在一个表中指定一个外键,而在另一个表中指定与其关联的键。

  • 指定用于比较各列的值的逻辑运算符(例如 = 或 <>)。

可以在 FROM 或 WHERE 子句中指定内部联接;而只能在 FROM 子句中指定外部联接。联接条件与 WHERE 和 HAVING 搜索条件相结合,用于控制从 FROM 子句所引用的基表中选定的行。

在 FROM 子句中指定联接条件有助于将这些联接条件与 WHERE 子句中可能指定的其他任何搜索条件分开,建议用这种方法来指定联接。简化的 ISO FROM 子句联接语法如下:

FROM first_tablejoin_typesecond_table [ON (join_condition)]

join_type 指定要执行的联接类型:内部联接、外部联接或交叉联接。join_condition 定义用于对每一对联接行进行求值的谓词。下面是 FROM 子句联接规范示例:

FROM Purchasing.ProductVendor JOIN Purchasing.Vendor
     ON (ProductVendor.VendorID = Vendor.VendorID)

下面是使用此联接的一个简单 SELECT 语句:

SELECT ProductID, Purchasing.Vendor.VendorID, Name
FROM Purchasing.ProductVendor JOIN Purchasing.Vendor
    ON (Purchasing.ProductVendor.VendorID = Purchasing.Vendor.VendorID)
WHERE StandardPrice > $10
  AND Name LIKE N'F%'
GO

此选择会返回某个公司所提供的一组产品以及供应商信息,该公司名以字母 F 开头,并且产品价格在 10 美元以上。

当在单个查询中引用多个表时,所有列引用都必须是明确的。在上例中,ProductVendor 和 Vendor 表都含有名为 VendorID 的一列。在查询所引用的两个或多个表中,任何重复的列名都必须用表名加以限定。此示例中对 Vendor 列的所有引用均已限定。

如果某个列名在查询用到的两个或多个表中不重复,则对该列的引用就必用表名加以限定。如上例所示。由于没有指明提供每个列的表,因此这样的 SELECT 语句有时会难以理解。如果所有的列都用它们的表名加以限定,将会提高查询的可读性。如果使用了表的别名,将会进一步提高可读性,尤其是当表名自身必须用数据库名和所有者名加以限定时。下例与上例相同,只不过分配了表的别名并且用表的别名对列加以限定,从而提高了可读性:

SELECT pv.ProductID, v.VendorID, v.Name
FROM Purchasing.ProductVendor pv JOIN Purchasing.Vendor v
    ON (pv.VendorID = v.VendorID)
WHERE StandardPrice > $10
    AND Name LIKE N'F%'

上例是在 FROM 子句中指定联接条件的,这是首选的方法。下列查询包含相同的联接条件,该联接条件在 WHERE 子句中指定:

SELECT pv.ProductID, v.VendorID, v.Name
FROM Purchasing.ProductVendor pv, Purchasing.Vendor v
WHERE pv.VendorID = v.VendorID
    AND StandardPrice > $10
    AND Name LIKE N'F%'

联接选择列表可以引用联接表中的所有列或任意一部分列。选择列表不必包含联接中每个表的列。例如,在三表联接中,只能用一个表作为中间表来联接另外两个表,而选择列表不必引用该中间表的任何列。

虽然联接条件通常使用相等比较 (=),但也可以像指定其他谓词一样指定其他比较运算符或关系运算符。有关详细信息,请参阅在表达式中使用运算符WHERE (Transact-SQL)

当 SQL Server 处理联接时,查询引擎会从多种可行的方法中选择最有效的方法来处理联接。由于各种联接的实际执行过程会采用多种不同的优化,因此无法可靠地预测。

联接条件中用到的列不必具有相同的名称或相同的数据类型。但如果数据类型不相同,则必须兼容,或者是可由 SQL Server 进行隐式转换的类型。如果数据类型不能进行隐式转换,则联接条件必须使用 CAST 函数显式转换数据类型。有关隐式和显式转换的详细信息,请参阅数据类型转换(数据库引擎)

大多数使用联接的查询可以用子查询(嵌套在其他查询中的查询)重写,并且大多数子查询可以重写为联接。有关子查询的详细信息,请参阅子查询基础知识

注意注意

不能在 ntext、text 或 image 列上直接联接表。但可以使用 SUBSTRING 在 ntext、text 或 image 列上间接联接表。例如,SELECT * FROM t1 JOIN t2 ON SUBSTRING(t1.textcolumn, 1, 20) = SUBSTRING(t2.textcolumn, 1, 20) 可对表 t1t2 中每个文本列的前 20 个字符进行两表内部联接。此外,另一种可以采用的比较两个表中 ntext 或 text 列的方法是用 WHERE 子句比较这些列的长度,例如:WHERE DATALENGTH(p1.pr_info) = DATALENGTH(p2.pr_info)。