聯結基礎觀念

透過使用聯結,您可以根據資料表之間的邏輯關聯性從二或多個資料表中擷取資料。聯結指出 Microsoft SQL Server 如何使用一個資料表的資料,以選取另一個資料表的資料列。

聯結條件定義兩個資料表在查詢中相關的方式:

  • 指定每個資料表中要用於聯結的資料行。典型的聯結條件會指定一個資料表的外部索引鍵,以及其在另一個資料表關聯的索引鍵。

  • 指定邏輯運算子 (例如 = 或 <>),以便用來比較資料行的數值。

內部聯結可指定於 FROM 或 WHERE 子句中。外部聯結則只能指定於 FROM 字句。聯結條件將與 WHERE 及 HAVING 搜尋條件合併,以控制由 FROM 子句參考之基底資料表中選出的資料列。

在 FROM 子句中指定聯結條件將有助於將它們從指定於 WHERE 子句中的任何其他搜尋條件分開,建議您以此方式來指定聯結。簡化的 ISO FROM 子句聯結語法為:

FROM first_table join_type second_table [ON (join_condition)]

join_type 指定執行的聯結類型是內部、外部或交叉聯結。join_condition 定義要為每一對聯結資料列評估的述詞。下列是 FROM 子句聯結規格的範例:

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

下列範例則是使用此聯結的簡單 SELECT 陳述式:

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

此選取將傳回公司名稱以字母 F 開頭之公司所供應的零件,並且產品的價格大於 $10 之任何組合的產品與供應商資訊。

若在單一查詢中參考多個資料表,所有的資料行參考都不可以模擬兩可。在先前的範例中,ProductVendor 和 Vendor 兩個資料表都有名稱為 BusinessEntityID 的資料行。查詢所參考的二或多個資料表中,若有任何資料行名稱重複,則必須以資料表名稱來加以限定。在範例中,所有對 Vendor 資料行的參考都有加以限定。

當查詢所使用的二或多個資料表中,資料行名稱都沒有重複,對資料行的參考就不需要以資料表名稱加以限定。如先前的範例所示。這樣的 SELECT 陳述式有時候很難瞭解,因為無法指出提供每個資料行的資料表。如果以資料表名稱限定所有資料行,可增進查詢的可讀性。如果還使用資料表別名,特別是當資料表名稱本身還需要以資料庫和擁有者名稱加以限定時,可進一步增進可讀性。下列是相同的範例,但是指定了資料表別名,並且以資料表別名限定資料行,以增進可讀性:

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

上個範例在 FROM 子句中指定聯結條件,這是較好的方式。下列查詢包含指定於 WHERE 子句中的相同聯結條件:

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

聯結的選取清單可參考聯結資料表中的所有資料行,或是資料行的任何子集。若要包含聯結中每個資料表的資料行,您並不需要用到選取清單。例如,在三個資料表的聯結中,一個資料表可作為第二個資料表與第三個資料表的橋樑,並且中間的資料表不需要有任何資料行參考於選取清單中。

雖然聯結條件通常擁有相等比較 (=),您也可以指定其他的比較或關聯式運算子,就如同其他述詞一樣。如需詳細資訊,請參閱<在運算式中使用運算子>與<WHERE (Transact-SQL)>。

當 SQL Server 處理聯結時,查詢引擎將從多種可能性選擇最有效率的處理聯結方式。不同聯結的實際執行可能會使用許多不同的最佳化方式,因此無法可靠地預測。

用於聯結條件的資料行,並不需要擁有相同的名稱或相同的資料類型。不過,若資料類型不一樣,它們必須是相容的類型,或是 SQL Server 可隱含轉換的類型。若資料類型無法隱含地轉換,聯結條件必須明確地使用 CAST 函數來轉換資料類型。如需有關隱含和明確轉換的詳細資訊,請參閱<資料類型轉換 (Database Engine)>。

大多數使用聯結的查詢都可使用子查詢重新改寫 (查詢巢狀於另一個查詢之內),而大多數的子查詢也可重新改寫成聯結。如需有關子查詢的詳細資訊,請參閱<子查詢基本原則>。

[!附註]

資料表無法直接聯結在 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)