1. 程式人生 > >T-SQL中的APPLY用法

T-SQL中的APPLY用法

原文出處:http://www.sqlservercentral.com/articles/Stairway+Series/121318/

 

從SQL Server 2005開始,微軟添加了一個新的運算子用於關聯一個帶有函式的結果集,並把函式應用於表/檢視中的每一個限定行中。這個運算子就是APPLY。從技術上來說,這個操作的底層邏輯並不是實際的“JOIN”,但由於它的用法更像是JOIN,所以通常會與關聯操作相關聯。APPLY操作分為兩種格式:CROSS APPLY或OUTER APPLY。在本文中會分別展示這兩種格式。

 

APPLY 簡介:
你是否曾經寫過SELECT語句去呼叫一個表值函式或把表值表示式的每一個記錄與表匹配?如果有過這樣的經歷,APPLY運算子會幫到你。APPLY分為CROSS APPLY和OUTER APPLY。

第一種格式叫CROSS APPLY。它從CROSSAPPLY的一邊提取表或資料集的每行的所需列值,然後作為輸入值傳輸到另外一邊的表值函式或表示式中。然後把所有關聯的值使用UNION ALL運算符合並。如果表值函式針對輸入資料沒有滿足呼叫條件時,函式將不返回輸出,並且這部分的表或結果集將不會出現在最終結果中,因為它不能與表值函式的資料關聯。

第二種格式叫OUTER APPLY。其行為和CROSSAPPLY類似,但返回不能呼叫表值函式/表示式的值。

為了更好理解這兩種格式,下面來演示一下:

 

測試資料和函式:

USE tempdb;
GO
IF object_id('
dbo.Product') IS NOT NULL DROP TABLE dbo.Product; IF object_id('dbo.SearchString') IS NOT NULL DROP TABLE dbo.SearchString; IF object_id('dbo.FindProductLike') IS NOT NULL DROP FUNCTION dbo.FindProductLike; CREATE TABLE dbo.Product ( ID INT IDENTITY , ProductNameVARCHAR(100) , Price MONEY ); INSERT INTO
dbo.Product VALUES ( 'Red SantaSuit', 199.99 ), ( 'Candy Canes', 1.99 ), ( 'Fake Snow', 2.99 ), ( 'Red Bells', 49.99 ), ( 'LED Lights', 6.99 ); CREATE TABLE dbo.SearchString ( ID INT IDENTITY , String VARCHAR(100) ); INSERT INTO dbo.SearchString VALUES ( 'Red' ), ( 'Lights' ), ( 'Star' ); GO CREATE FUNCTION dbo.FindProductLike ( @FindString VARCHAR(100) ) RETURNS TABLE AS RETURN ( SELECT ProductName, Price FROM dbo.Product WHERE ProductName LIKE '%' + @FindString + '%' )

建立表和表值函式

 

 

 

上面的指令碼中建立了一個叫做Product的表,包含了5個不同的產品。同時也建立了一個叫做SearchString的表,包含了3個不同的字串。最後建立一個叫做FindProductLike的表值函式。該函式接收一個@FindString引數,並在Product表中找出所有包含@FindString的ProductName。

 

使用CROSS APPLY 運算子:
CROSS APPLY會對相關聯的每一行都應用該函式

 

USE tempdb;
GO
SELECT *
FROM dbo.SearchString AS S
CROSS APPLYdbo.FindProductLike(S.String);

 

結果如下:
 

 

 

回看程式碼可以看到,程式碼中使用CROSSAPPLY關聯SearchString表中的結果集和FindProductLike表值函式。CROSS APPLY從SearchString中獲取String值,然後呼叫函式FindProductLike。如果函式返回資料,則與SearchString的行關聯。

前兩行的資料來自於字串“Red”,當“Red”傳輸給函式後,返回包含該值的ProductName和Price,然後和SearchString關聯,把包含“Red”值的產品返回到結果集中。第三行資料和前兩行的產生原理一致,但是是由“Lights”產生。字串“Star”由於沒有在Product中得到匹配值,所以不返回結果。

 

 

使用OUTER APPLY 運算子:
該操作符和CROSS APPLY的唯一區別是返回所有資料,包括沒有匹配的值:

USE tempdb;
GO
SELECT *
FROM dbo.SearchString AS S
OUTER APPLYdbo.FindProductLike(S.String);

 


 

從結果中可以看出,對於字串“Star”,OUTER APPLY也返回結果,只是返回NULL。

 

使用表值表示式:
下面演示一下使用表值表示式與APPLY的操作。

USE tempdb;
GO
SELECT * FROM dbo.SearchString as S
CROSS APPLY
(SELECT ProductName, Price
FROM dbo.Product
WHERE ProductName like '%' + S.String + '%') as X

 

 


 

從結果上來看,和CROSS APPLY無異,僅僅是把表值函式換成了表值表示式。

 

 

總結:
APPLY運算可以把資料集中的資料與表值函式或表值表示式關聯,使用APPLY可以針對表值函式或表示式的資料集進行基於集合的查詢。在這種情況下可以考慮使用APPLY運算子。