子查詢基本原則
子查詢是指在 SELECT、INSERT、UPDATE 或 DELETE 陳述式中,或在另一個子查詢之中為巢狀的。子查詢允許在運算式的任何位置使用。在此範例中,子查詢將在 SELECT 陳述式中,當做名為 MaxUnitPrice 的資料行運算式使用。
USE AdventureWorks2008R2;
GO
SELECT Ord.SalesOrderID, Ord.OrderDate,
(SELECT MAX(OrdDet.UnitPrice)
FROM AdventureWorks.Sales.SalesOrderDetail AS OrdDet
WHERE Ord.SalesOrderID = OrdDet.SalesOrderID) AS MaxUnitPrice
FROM AdventureWorks2008R2.Sales.SalesOrderHeader AS Ord
子查詢也稱為內部查詢或內部選取,而包含子查詢的陳述式又稱為外部查詢或外部選取。
許多包含子查詢的 Transact-SQL 陳述式也可以構成聯結。其他的問題也只能以子查詢提出。在 Transact-SQL 中,包含子查詢的陳述式與語意上相等版本之間的效能,通常沒有差異。然而,在某些必須檢查存在性的情況下,聯結將可產生更好的效能。否則,必須針對外部查詢的每個結果來處理巢狀查詢,以確保能消除重複性。在這樣的情況下,聯結方法將會產生更好的結果。下列範例顯示 SELECT 子查詢以及可傳回相同結果集的聯結 SELECT:
/* SELECT statement built using a subquery. */
SELECT Name
FROM AdventureWorks2008R2.Production.Product
WHERE ListPrice =
(SELECT ListPrice
FROM AdventureWorks2008R2.Production.Product
WHERE Name = 'Chainring Bolts' );
/* SELECT statement built using a join that returns
the same result set. */
SELECT Prd1. Name
FROM AdventureWorks2008R2.Production.Product AS Prd1
JOIN AdventureWorks2008R2.Production.Product AS Prd2
ON (Prd1.ListPrice = Prd2.ListPrice)
WHERE Prd2. Name = 'Chainring Bolts';
外部 SELECT 陳述式中的巢狀子查詢擁有下列元件:
包含一般選取清單元件的一般 SELECT 查詢。
包含一或多個資料表或檢視名稱的一般 FROM 子句。
選擇性的 WHERE 子句。
選擇性的 GROUP BY 子句。
選擇性的 HAVING 子句。
子查詢的 SELECT 查詢永遠都會以括號括住。它無法包含 COMPUTE 或 FOR BROWSE 子句,而且在未指定 TOP 子句時,只能包含 ORDER BY 子句。
可以將子查詢套疊在外部 SELECT、INSERT、UPDATE 或 DELETE 陳述式的 WHERE 或 HAVING 子句中,或是位於另一個子查詢之中。巢狀層級最多可達 32 層,不過此限制仍將取決於可用的記憶體,以及查詢中其他運算式的複雜性。個別的查詢可能無法支援 32 層的巢狀。若子查詢傳回單一數值的話,它將可出現在能夠使用運算式的任何位置。
如果資料表只出現在子查詢中,而沒有出現在外部查詢裡面,那麼該資料表的資料行並不能包含於輸出之中 (外部查詢的選取清單)。
包含子查詢的陳述式通常會採用下列格式之一:
WHERE expression [NOT] IN (subquery)
WHERE expression comparison_operator [ANY | ALL] (subquery)
WHERE [NOT] EXISTS (subquery)
在某些 Transact-SQL 陳述式中,可以像獨立查詢一樣評估子查詢。在概念上,在外部查詢中將以子查詢的結果來替代 (雖然這不一定是 Microsoft SQL Server 實際上處理包含子查詢之 Transact-SQL 陳述式的作法)。
子查詢有三種基本類型。分別為:
運作於清單,並以 IN 提出或是 ANY 或 ALL 修改之比較運算子提出。
以未修改的比較運算子提出,並且必須傳回單一數值。
EXISTS 所提出的存在測試。