联接基础知识
通过联接,可以从两个或多个表中根据各个表之间的逻辑关系来检索数据。联接指明了 Microsoft SQL Server 2005 应如何使用一个表中的数据来选择另一个表中的行。
联接条件可通过以下方式定义两个表在查询中的关联方式:
- 指定每个表中要用于联接的列。典型的联接条件在一个表中指定一个外键,而在另一个表中指定与其关联的键。
- 指定用于比较各列的值的逻辑运算符(例如 = 或 <>)。
可以在 FROM 或 WHERE 子句中指定内部联接;而只能在 FROM 子句中指定外部联接。联接条件与 WHERE 和 HAVING 搜索条件相结合,用于控制从 FROM 子句所引用的基表中选定的行。
在 FROM 子句中指定联接条件有助于将这些联接条件与 WHERE 子句中可能指定的其他任何搜索条件分开,建议用这种方法来指定联接。简化的 SQL-92 FROM 子句联接语法如下:
FROM first_table join_type second_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 处理联接时,查询引擎会从多种可行的方法中选择最有效的方法来处理联接。尽管各种联接的实际执行过程会采用多种不同的优化方式,但是逻辑顺序均为:
- 应用 FROM 子句中的联接条件。
- 应用 WHERE 子句中的联接条件和搜索条件。
- 应用 HAVING 子句中的搜索条件。
如果在 FROM 和 WHERE 子句之间移动条件,则这一顺序有时会影响查询结果。
联接条件中用到的列不必具有相同的名称或相同的数据类型。但如果数据类型不相同,则必须兼容,或者是可由 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) 可对表 t1 和 t2 中每个文本列的前 20 个字符进行两表内部联接。此外,另一种可以采用的比较两个表中的 ntext 或 text 列的方法是用 WHERE 子句比较列的长度,例如:WHERE DATALENGTH(p1.pr_info) = DATALENGTH(p2.pr_info) 。 |