SQL 預存程序 預存程序是編譯成一個執行計劃的一組 Transact-SQL 陳述式。 Microsoft® SQL Server™ 2000 預存程序傳回資料的方式有四: 輸出參數,它可以傳回資料 (如整數或字元值) 或資料指標 (Cursor) 變數 (資料指標是可以一次擷取一列的結果集)。 傳回碼 (Return Code),這一定是整數值。 每個 SELECT 陳述式 (不論包含在預存程序中,或是預存程序呼叫的任何其他預存程序中) 的結果集。 可以在預存程序外引用的全域資料指標。 預存程序有助於在應用程式間達成一致的邏輯實作。對於必須經常執行的工作,可以將所需的 SQL 陳述式與邏輯設計與編寫在一個預存程序中,並一起進行測試。必須執行該工作的每個應用程式就只要執行預存程序即可。將業務邏輯編寫進一個單一預存程序中,也可以提供單一的控制點,以確保正確地執行業務邏輯。 預存程序也可以改善效能。許多工作都實作成一系列的 SQL 陳述式。然後對第一個 SQL 陳述式套用條件式邏輯,再決定接著要執行哪些 SQL 陳述式。如果將這些 SQL 陳述式與條件式邏輯寫進預存程序,它們就成為伺服器上一個執行計劃的一部分。使得結果不必傳回用戶端來套用條件式邏輯;所有工作都在伺服器上進行。以下範例中的 IF 陳述式示範如何在程序中內嵌條件式邏輯,以免將結果集傳回應用程式: IF (@QuantityOrdered < (SELECT QuantityOnHand FROM Inventory WHERE PartID = @PartOrdered) ) BEGIN -- SQL statements to update tables and process order. END ELSE BEGIN -- SELECT statement to retrieve the IDs of alternate items -- to suggest as replacements to the customer. END 應用程式不必傳送程序中的所有 SQL 陳述式:它們只要傳送一個 EXECUTE 或 CALL 陳述式,而且在陳述式中包含程序的名稱與參數值。 預存程序也可以讓使用者不必知道資料庫中資料的細節。如果一組預存程序支援使用者必須進行的所有業務功能,使用者永遠都不必直接存取資料表;他們只要執行形成業務處理程序的預存程序,而這些業務處理程序是他們原本就很熟悉的。 使用 SQL Server 系統預存程序會將使用者與系統資料表隔離,這就是預存程序這種功能的一個實例。SQL Server 包括一組系統預存程序,名稱都是以 sp_ 開始。執行 SQL Server 系統所需的所有管理工作都可由這些系統預存程序支援。所以只要使用 Transact-SQL 有關管理的陳述式 (如 CREATE TABLE) 或這些系統預存程序,就可以管理 SQL Server 系統,永遠都不必直接更新系統資料表。 預存程序與執行計劃 在 SQL Server 6.5 版 (與更舊版) 中,預存程序是將執行計劃部分預先編譯的一種方法。在建立預存程序時,經過部分編譯的執行計劃會儲存在系統資料表中。所以當時執行預存程序比執行 SQL 陳述式有效率,因為 SQL Server 不必完整編譯執行計劃,而只要完成程序預存計劃的最佳化。同時,預存程序完整編譯的執行計劃過去會保留在 SQL Server 程序快取區中,所以之後執行預存程序時,可以使用預先編譯的執行計劃。 現在,SQL Server 2000 與 SQL Server 7.0 版在陳述式處理方面做了一些變更,將預存程序的許多效能優點擴大到所有 SQL 陳述式。在建立預存程序時,SQL Server 2000 與 SQL Server 7.0 並不會儲存部分編譯的計劃。而是像其他任何 Transact-SQL 陳述式一樣,在執行時間才編譯預存程序。SQL Server 2000 與 SQL Server 7.0 將所有 SQL 陳述式的執行計劃保留在程序快取區中,而不只是預存程序的執行計劃。資料庫引擎使用有效率的演算法來比較新的 Transact-SQL 陳述式與現有執行計劃的 Transact-SQL 陳述式。如果資料庫引擎判定新的 Transact-SQL 陳述式符合現有執行計劃的 Transact-SQL 陳述式,就會重複使用該計劃。藉由將重複使用執行計劃擴大到所有 SQL 陳述式,就減少了預先編譯預存程序的相對效能優點。 SQL Server 2000 與 SQL Server 7.0 版提供新的替代方式來處理 SQL 陳述式。如需詳細資訊,請參閱查詢處理程式架構。 暫時性預存程序 SQL Server 2000 也支援暫時性預存程序,這就像暫存資料表一樣會在中斷連線時自動卸除。暫時性預存程序儲存在 tempdb 中,它在連線到舊版 SQL Server 時非常有用。當應用程式建立要執行好幾次的動態 Transact-SQL 陳述式時,就可以使用暫時性預存程序。您不必每次重新編譯 Transact-SQL 陳述式,而可以建立暫時性預存程序,讓它在第一次執行時編譯,之後就可以一再執行預先編譯的計劃。然而若大量使用暫時性預存程序,可能導致 tempdb 中發生爭奪系統資料表的現象。 SQL Server 2000 與 SQL Server 7.0 的兩項功能去除了使用暫時性預存程序的需要: 可重複使用先前的 SQL 陳述式的執行計劃。配合使用新的 sp_executesql 系統預存程序,這個功能更是特別強大。 不必使用任何預存程序,就能支援 OLE DB 與 ODBC (開放式資料庫連接) 的準備/執行模型。 如需有關使用暫時性預存程序之替代方式的詳細資訊,請參閱執行計劃快取與重複使用。 預存程序範例 這個簡單的預存程序範例示範預存程序傳回資料的三種方法: 它先發出 SELECT 陳述式,該陳述式會傳回摘要sales 資料表中商店的訂購活動的結果集。 然後發出 SELECT 陳述式填上輸出參數。 最後,利用一個使用 SELECT 陳述式的 RETURN 陳述式,傳回一個整數。通常使用傳回碼 (Return Code) 是傳回錯誤檢查資訊。這個程序的執行未發生錯誤,所以傳回別的值,說明如何填入傳回碼。 USE Northwind GO DROP PROCEDURE OrderSummary GO CREATE PROCEDURE OrderSummary @MaxQuantity INT OUTPUT AS -- SELECT to return a result set summarizing -- employee sales. SELECT Ord.EmployeeID, SummSales = SUM(OrDet.UnitPrice * OrDet.Quantity) FROM Orders AS Ord JOIN [Order Details] AS OrDet ON (Ord.OrderID = OrDet.OrderID) GROUP BY Ord.EmployeeID ORDER BY Ord.EmployeeID -- SELECT to fill the output parameter with the -- maximum quantity from Order Details. SELECT @MaxQuantity = MAX(Quantity) FROM [Order Details] -- Return the number of all items ordered. RETURN (SELECT SUM(Quantity) FROM [Order Details]) GO -- Test the stored procedure. -- DECLARE variables to hold the return code -- and output parameter. DECLARE @OrderSum INT DECLARE @LargestOrder INT -- Execute the procedure, which returns -- the result set from the first SELECT. EXEC @OrderSum = OrderSummary @MaxQuantity = @LargestOrder OUTPUT -- Use the return code and output parameter. PRINT 'The size of the largest single order was: ' + CONVERT(CHAR(6), @LargestOrder) PRINT 'The sum of the quantities ordered was: ' + CONVERT(CHAR(6), @OrderSum) GO 執行此範例的輸出為: EmployeeID SummSales ----------- -------------------------- 1 202,143.71 2 177,749.26 3 213,051.30 4 250,187.45 5 75,567.75 6 78,198.10 7 141,295.99 8 133,301.03 9 82,964.00 The size of the largest single order was: 130 The sum of the quantities ordered was: 51317