本質(zhì)上沒區(qū)別。只是函數(shù)有如:只能返回一個變量的限制。而存儲過程可以返回多個。而函數(shù)是可以嵌入在sql中使用的,可以在select中調(diào)用,而存儲過程不行。執(zhí)行的本質(zhì)都一樣。
函數(shù)限制比較多,比如不能用臨時表,只能用表變量.還有一些函數(shù)都不可用等等.而存儲過程的限制相對就比較少
由于我現(xiàn)在基本上是DBA的工作,因此平時也看一些數(shù)據(jù)庫方面的書籍。但是我一直對存儲過程和函數(shù)之間的區(qū)別掌握不透。我向來認為存儲過程可以實現(xiàn)的操作,函數(shù)也一樣可以實現(xiàn)。最近,剛好大學的老師給我們上SQL-Server的課程,我對這個問題的疑惑終于慢慢解開。今天晚上順便看了些網(wǎng)上的資料,覺得以下分析比較合理:
1. 一般來說,存儲過程實現(xiàn)的功能要復雜一點,而函數(shù)的實現(xiàn)的功能針對性比較強。
2. 對于存儲過程來說可以返回參數(shù),而函數(shù)只能返回值或者表對象。
3. 存儲過程一般是作為一個獨立的部分來執(zhí)行,而函數(shù)可以作為查詢語句的一個部分來調(diào)用,由于函數(shù)可以返回一個表對象,因此它可以在查詢語句中位于FROM關(guān)鍵字的后面。
4. 當存儲過程和函數(shù)被執(zhí)行的時候,SQL Manager會到procedure cache中去取相應的查詢語句,如果在procedure cache里沒有相應的查詢語句,SQL Manager就會對存儲過程和函數(shù)進行編譯。
Procedure cache中保存的是執(zhí)行計劃 (execution plan) ,當編譯好之后就執(zhí)行procedure cache中的execution plan,之后SQL SERVER會根據(jù)每個execution plan的實際情況來考慮是否要在cache中保存這個plan,評判的標準一個是這個execution plan可能被使用的頻率;其次是生成這個plan的代價,也就是編譯的耗時。保存在cache中的plan在下次執(zhí)行時就不用再編譯了。
存儲過程和用戶自定義函數(shù)具體的區(qū)別
先看定義:
存儲過程
存儲過程可以使得對數(shù)據(jù)庫的管理、以及顯示關(guān)于數(shù)據(jù)庫及其用戶信息的工作容易得多。存儲過程是 SQL 語句和可選控制流語句的預編譯集合,以一個名稱存儲并作為一個單元處理。存儲過程存儲在數(shù)據(jù)庫內(nèi),可由應用程序通過一個調(diào)用執(zhí)行,而且允許用戶聲明變量、有條件執(zhí)行以及其它強大的編程功能。
存儲過程可包含程序流、邏輯以及對數(shù)據(jù)庫的查詢。它們可以接受參數(shù)、輸出參數(shù)、返回單個或多個結(jié)果集以及返回值。
可以出于任何使用 SQL 語句的目的來使用存儲過程,它具有以下優(yōu)點:
可以在單個存儲過程中執(zhí)行一系列 SQL 語句。
可以從自己的存儲過程內(nèi)引用其它存儲過程,這可以簡化一系列復雜語句。
存儲過程在創(chuàng)建時即在服務器上進行編譯,所以執(zhí)行起來比單個 SQL 語句快。
用戶定義函數(shù)
函數(shù)是由一個或多個 Transact-SQL 語句組成的子程序,可用于封裝代碼以便重新使用。Microsoft? SQL Server? 2000 并不將用戶限制在定義為 Transact-SQL 語言一部分的內(nèi)置函數(shù)上,而是允許用戶創(chuàng)建自己的用戶定義函數(shù)。
可使用 CREATE FUNCTION 語句創(chuàng)建、使用 ALTER FUNCTION 語句修改、以及使用 DROP FUNCTION 語句除去用戶定義函數(shù)。每個完全合法的用戶定義函數(shù)名 (database_name.owner_name.function_name) 必須唯一。
必須被授予 CREATE FUNCTION 權(quán)限才能創(chuàng)建、修改或除去用戶定義函數(shù)。不是所有者的用戶在 Transact-SQL 語句中使用某個函數(shù)之前,必須先給此用戶授予該函數(shù)的適當權(quán)限。若要創(chuàng)建或更改在 CHECK 約束、DEFAULT 子句或計算列定義中引用用戶定義函數(shù)的表,還必須具有函數(shù)的 REFERENCES 權(quán)限。
在函數(shù)中,區(qū)別處理導致刪除語句并且繼續(xù)在諸如觸發(fā)器或存儲過程等模式中的下一語句的 Transact-SQL 錯誤。在函數(shù)中,上述錯誤會導致停止執(zhí)行函數(shù)。接下來該操作導致停止喚醒調(diào)用該函數(shù)的語句。
用戶定義函數(shù)的類型
SQL Server 2000 支持三種用戶定義函數(shù):
標量函數(shù)
內(nèi)嵌表值函數(shù)
多語句表值函數(shù)
用戶定義函數(shù)采用零個或更多的輸入?yún)?shù)并返回標量值或表。函數(shù)最多可以有 1024 個輸入?yún)?shù)。當函數(shù)的參數(shù)有默認值時,調(diào)用該函數(shù)時必須指定默認 DEFAULT 關(guān)鍵字才能獲取默認值。該行為不同于在存儲過程中含有默認值的參數(shù),而在這些存儲過程中省略該函數(shù)也意味著省略默認值。用戶定義函數(shù)不支持輸出參數(shù)。
標量函數(shù)返回在 RETURNS 子句中定義的類型的單個數(shù)據(jù)值。可以使用所有標量數(shù)據(jù)類型,包括 bigint 和 sql_variant。不支持 timestamp 數(shù)據(jù)類型、用戶定義數(shù)據(jù)類型和非標量類型(如 table 或 cursor)。在 BEGIN...END 塊中定義的函數(shù)主體包含返回該值的 Transact-SQL 語句系列。返回類型可以是除 text、ntext、image、cursor 和 timestamp 之外的任何數(shù)據(jù)類型。
表值函數(shù)返回 table。對于內(nèi)嵌表值函數(shù),沒有函數(shù)主體;表是單個 SELECT 語句的結(jié)果集。對于多語句表值函數(shù),在 BEGIN...END 塊中定義的函數(shù)主體包含 TRANSACT-SQL 語句,這些語句可生成行并將行插入將返回的表中。有關(guān)內(nèi)嵌表值函數(shù)的更多信息,請參見內(nèi)嵌用戶定義函數(shù)。有關(guān)表值函數(shù)的更多信息,請參見返回 table 數(shù)據(jù)類型的用戶定義函數(shù)。
BEGIN...END 塊中的語句不能有任何副作用。函數(shù)副作用是指對具有函數(shù)外作用域(例如數(shù)據(jù)庫表的修改)的資源狀態(tài)的任何永久性更改。函數(shù)中的語句唯一能做的更改是對函數(shù)上的局部對象(如局部游標或局部變量)的更改。不能在函數(shù)中執(zhí)行的操作包括:對數(shù)據(jù)庫表的修改,對不在函數(shù)上的局部游標進行操作,發(fā)送電子郵件,嘗試修改目錄,以及生成返回至用戶的結(jié)果集。
函數(shù)中的有效語句類型包括:
DECLARE 語句,該語句可用于定義函數(shù)局部的數(shù)據(jù)變量和游標。
為函數(shù)局部對象賦值,如使用 SET 給標量和表局部變量賦值。
游標操作,該操作引用在函數(shù)中聲明、打開、關(guān)閉和釋放的局部游標。不允許使用 FETCH 語句將數(shù)據(jù)返回到客戶端。僅允許使用 FETCH 語句通過 INTO 子句給局部變量賦值。
控制流語句。
SELECT 語句,該語句包含帶有表達式的選擇列表,其中的表達式將值賦予函數(shù)的局部變量。
INSERT、UPDATE 和 DELETE 語句,這些語句修改函數(shù)的局部 table 變量。
EXECUTE 語句,該語句調(diào)用擴展存儲過程。
在查詢中指定的函數(shù)的實際執(zhí)行次數(shù)在優(yōu)化器生成的執(zhí)行計劃間可能不同。示例為 WHERE 子句中的子查詢喚醒調(diào)用的函數(shù)。子查詢及其函數(shù)執(zhí)行的次數(shù)會因優(yōu)化器選擇的訪問路徑而異。
用戶定義函數(shù)中不允許使用會對每個調(diào)用返回不同數(shù)據(jù)的內(nèi)置函數(shù)。用戶定義函數(shù)中不允許使用以下內(nèi)置函數(shù):
@@CONNECTIONS @@PACK_SENT GETDATE
@@CPU_BUSY @@PACKET_ERRORS GetUTCDate
@@IDLE @@TIMETICKS NEWID
@@IO_BUSY @@TOTAL_ERRORS RAND
@@MAX_CONNECTIONS @@TOTAL_READ TEXTPTR
@@PACK_RECEIVED @@TOTAL_WRITE
架構(gòu)綁定函數(shù)
CREATE FUNCTION 支持 SCHEMABINDING 子句,后者可將函數(shù)綁定到它引用的任何對象(如表、視圖和其它用戶定義函數(shù))的架構(gòu)。嘗試對架構(gòu)綁定函數(shù)所引用的任何對象執(zhí)行 ALTER 或 DROP 都將失敗。
必須滿足以下條件才能在 CREATE FUNCTION 中指定 SCHEMABINDING:
該函數(shù)所引用的所有視圖和用戶定義函數(shù)必須是綁定到架構(gòu)的。
該函數(shù)所引用的所有對象必須與函數(shù)位于同一數(shù)據(jù)庫中。必須使用由一部分或兩部分構(gòu)成的名稱來引用對象。
必須具有對該函數(shù)中引用的所有對象(表、視圖和用戶定義函數(shù))的 REFERENCES 權(quán)限。
可使用 ALTER FUNCTION 刪除架構(gòu)綁定。ALTER FUNCTION 語句將通過不帶 WITH SCHEMABINDING 指定函數(shù)來重新定義函數(shù)。
調(diào)用用戶定義函數(shù)
當調(diào)用標量用戶定義函數(shù)時,必須提供至少由兩部分組成的名稱:
SELECT *, MyUser.MyScalarFunction()
FROM MyTable
可以使用一個部分構(gòu)成的名稱調(diào)用表值函數(shù):
SELECT *
FROM MyTableFunction()
然而,當調(diào)用返回表的 SQL Server 內(nèi)置函數(shù)時,必須將前綴 :: 添加至函數(shù)名:
SELECT * FROM ::fn_helpcollations()
可在 Transact-SQL 語句中所允許的函數(shù)返回的相同數(shù)據(jù)類型表達式所在的任何位置引用標量函數(shù),包括計算列和 CHECK 約束定義。例如,下面的語句創(chuàng)建一個返回 decimal 的簡單函數(shù):
CREATE FUNCTION CubicVolume
-- Input dimensions in centimeters
(@CubeLength decimal(4,1), @CubeWidth decimal(4,1),
@CubeHeight decimal(4,1) )
RETURNS decimal(12,3) -- Cubic Centimeters.
AS
BEGIN
RETURN ( @CubeLength * @CubeWidth * @CubeHeight )
END
然后可以在允許整型表達式的任何地方(如表的計算列中)使用該函數(shù):
CREATE TABLE Bricks
(
BrickPartNmbr int PRIMARY KEY,
BrickColor nchar(20),
BrickHeight decimal(4,1),
BrickLength decimal(4,1),
BrickWidth decimal(4,1),
BrickVolume AS
(
dbo.CubicVolume(BrickHeight,
BrickLength, BrickWidth)
)
)
dbo.CubicVolume 是返回標量值的用戶定義函數(shù)的一個示例。RETURNS 子句定義由該函數(shù)返回的值的標量數(shù)據(jù)類型。BEGIN...END 塊包含一個或多個執(zhí)行該函數(shù)的 Transact-SQL 語句。該函數(shù)中的每個 RETURN 語句都必須具有一個參數(shù),可返回具有在 RETURNS 子句中指定的數(shù)據(jù)類型(或可隱性轉(zhuǎn)換為 RETURNS 中指定類型的數(shù)據(jù)類型)的數(shù)據(jù)值。RETURN 參數(shù)的值是該函數(shù)返回的值。