天天看點

存儲過程與函數的差別

核心提示:本質上沒差別。隻是函數有限制隻能傳回一個标量,而存儲過程可以傳回多個。并且函數是可以嵌入在SQL中使用的,可以在SELECT等SQL語句中調用,而存儲過程不行。執行的本質都一樣。

   函數限制比較多,如不能用臨時表,隻能用表變量等,而存儲過程的限制相對就比較少。

   1. 一般來說,存儲過程實作的功能要複雜一點,而函數的實作的功能針對性比較強。

   2. 對于存儲過程來說可以傳回參數,而函數隻能傳回值或者表對象。

   3. 存儲過程一般是作為一個獨立的部分來執行,而函數可以作為查詢語句的一個部分來調用,由于函數

      可以傳回一個表對象,是以它可以在查詢語句中位于FROM關鍵字的後面。

   4. 當存儲過程和函數被執行的時候,SQL Manager會到procedure cache中去取相應的查詢語句,如果在

      procedure cache裡沒有相應的查詢語句,SQL Manager就會對存儲過程和函數進行編譯。

Procedurecache

:中儲存的是執行計劃,當編譯好之後就執行procedure cache中的execution plan,之後SQL SERVER會根據每個execution plan的實際情況來考慮是否要在cache中儲存這個plan,評判的标準一個是這個execution plan可能被使用的頻率;其次是生成這個plan的代價,也就是編譯的耗時。儲存在cache中的plan在下次執行時就不用再編譯了。

存儲過程和函數具體的差別:

    存儲過程:可以使得對的管理、以及顯示關于及其使用者資訊的工作容易得多。存儲過程是 SQL 語句和可選控制流語句的預編譯集合,以一個名稱存儲并作為一個單元處理。存儲過程存儲在資料庫内,可由應用程式通過一個調用執行,而且允許使用者聲明變量、有條件執行以及其它強大的程式設計功能。存儲過程可包含程式流、邏輯以及對資料庫的查詢。它們可以接受參數、輸出參數、傳回單個或多個結果集以及傳回值。

   可以出于任何使用 SQL 語句的目的來使用存儲過程,它具有以下優點:

   (1)功能強大,限制少。

   (2)可以在單個存儲過程中執行一系列 SQL 語句。

   (3)可以從自己的存儲過程内引用其它存儲過程,這可以簡化一系列複雜語句。

   (4)存儲過程在建立時即在上進行編譯,是以執行起來比單個 SQL 語句快。

   (5)可以有多個傳回值,即多個輸出參數,并且可以使用SELECT傳回結果集。

   函數:是由一個或多個 SQL 語句組成的子程式,可用于封裝代碼以便重新使用。自定義函數諸多限制,有許多語句不能使用,許多功能不能實作。函數可以直接引用傳回值,用表變量傳回記錄集。但是,使用者定義函數不能用于執行一組修改全局資料庫狀态的操作。 

補充:

   前面有一句,“可以處于任何使用SQL語句的目的來使用存儲過程”。這裡想說的是,有些時候有些地方使用函數或許會更友善些。例如,存在這樣一個表:Temperature(Year, Month, Day, T02, T08, T14, T20),其中Year,Month,Day是時間字段,T02, T08, T14, T20是指2時、8時、14時、20時四個時刻對應的溫度值,這些溫度值可為空。現在,要求統計2008年5月份的平均溫度。

   或許大家會這樣寫:

    SELECT (AVG(T02)+AVG(T08)+AVG(T14)+AVG(T20))/4 FROM Temperature WHERE Year=2008 AND Month=5

   如果不考慮空值的話,這樣完全正确,但是考慮空值的話,如果根本沒有統計02時的溫度,那麼AVG(T02)将為NULL,然後進行所有運算的結果都将為NULL。這顯然是不正确的。

   這裡可以建立一個自定義函數,然後使用一個SELECT語句即可查詢:

   SELECT AVG(user.Average(T02,T08,T14,T20)) FROM Temperature WHERE Year=2008 AND Month=5

總結:

   使用者自定義函數在處理同一資料行中的各個字段時,特别友善有用。雖然這裡使用存儲過程也能達到查詢目的,但是顯然沒有使用函數友善。而且,即使使用存儲過程也無法處理SELECT查詢中的同一資料行中的各個字段的運算。因為存儲過程不傳回值,使用時隻能單獨調用;而函數卻能出現在能放置表達式的任何位置。

CREATE FUNCTION user.Average

(

   @T02 float,

   @T08 float,

   @T14 float,

   @T20 float

)

RETURNS float AS 

BEGIN

DECLARE @sum float

DECLARE @num int

DECLARE @Ret float

SET @sum=0

SET @num=0

IF @T02 IS NOT NULL

    SET @sum = @sum + @T02

    SET @num = @num + 1

END

IF @T08 IS NOT NULL

    SET @sum = @sum + @T08

IF @T14 IS NOT NULL

    SET @sum = @sum + @T14

IF @T20 IS NOT NULL

    SET @sum = @sum + @T20

IF @num>0  SET @Ret = @sum / @num

Return @Ret

END

GO