表示最多可以指定 2.100 個參數(shù)的占位符。 {RECOMPILE | ENCRYPTION | RECOMPILE, ENCRYPTION} RECOMPILE 表明 SQL Server 不會緩存該過程的計劃,該過程將在運行時重新編譯。在使用非典型值或臨時值而不希望覆蓋緩存在內(nèi)存中的執(zhí)行計劃時,請使用 RECOMPILE 選項。 ENCRYPTION 表示 SQL Server 加密 syscomments 表中包含 CREATE PROCEDURE 語句文本的條目。使用 ENCRYPTION 可防止將過程作為 SQL Server 復(fù)制的一部分發(fā)布。 說明 在升級過程中,SQL Server 利用存儲在 syscomments 中的加密注釋來重新創(chuàng)建加密過程。 FOR REPLICATION 指定不能在訂閱服務(wù)器上執(zhí)行為復(fù)制創(chuàng)建的存儲過程。.使用 FOR REPLICATION 選項創(chuàng)建的存儲過程可用作存儲過程篩選,且只能在復(fù)制過程中執(zhí)行。本選項不能和 WITH RECOMPILE 選項一起使用。 AS 指定過程要執(zhí)行的操作。 sql_statement 過程中要包含的任意數(shù)目和類型的 Transact-SQL 語句。但有一些限制。
是表示此過程可以包含多條 Transact-SQL 語句的占位符。
注釋 存儲過程的最大大小為 128 MB。 用戶定義的存儲過程只能在當(dāng)前數(shù)據(jù)庫中創(chuàng)建(臨時過程除外,臨時過程總是在 tempdb 中創(chuàng)建)。在單個批處理中,CREATE PROCEDURE 語句不能與其它 Transact-SQL 語句組合使用。 默認(rèn)情況下,參數(shù)可為空。如果傳遞 NULL 參數(shù)值并且該參數(shù)在 CREATE 或 ALTER TABLE 語句中使用,而該語句中引用的列又不允許使用 NULL,則 SQL Server 會產(chǎn)生一條錯誤信息。為了防止向不允許使用 NULL 的列傳遞 NULL 參數(shù)值,應(yīng)向過程中添加編程邏輯或為該列使用默認(rèn)值(使用 CREATE 或 ALTER TABLE 的 DEFAULT 關(guān)鍵字)。 建議在存儲過程的任何 CREATE TABLE 或 ALTER TABLE 語句中都為每列顯式指定 NULL 或 NOT NULL,例如在創(chuàng)建臨時表時。ANSI_DFLT_ON 和 ANSI_DFLT_OFF 選項控制 SQL Server 為列指派 NULL 或 NOT NULL 特性的方式(如果在 CREATE TABLE 或 ALTER TABLE 語句中沒有指定的話)。如果某個連接執(zhí)行的存儲過程對這些選項的設(shè)置與創(chuàng)建該過程的連接的設(shè)置不同,則為第二個連接創(chuàng)建的表列可能會有不同的為空性,并且表現(xiàn)出不同的行為方式。如果為每個列顯式聲明了 NULL 或 NOT NULL,那么將對所有執(zhí)行該存儲過程的連接使用相同的為空性創(chuàng)建臨時表。 在創(chuàng)建或更改存儲過程時,SQL Server 將保存 SET QUOTED_IDENTIFIER 和 SET ANSI_NULLS 的設(shè)置。執(zhí)行存儲過程時,將使用這些原始設(shè)置。因此,所有客戶端會話的 SET QUOTED_IDENTIFIER 和 SET ANSI_NULLS 設(shè)置在執(zhí)行存儲過程時都將被忽略。在存儲過程中出現(xiàn)的 SET QUOTED_IDENTIFIER 和 SET ANSI_NULLS 語句不影響存儲過程的功能。 其它 SET 選項(例如 SET ARITHABORT、SET ANSI_WARNINGS 或 SET ANSI_PADDINGS)在創(chuàng)建或更改存儲過程時不保存。如果存儲過程的邏輯取決于特定的設(shè)置,應(yīng)在過程開頭添加一條 SET 語句,以確保設(shè)置正確。從存儲過程中執(zhí)行 SET 語句時,該設(shè)置只在存儲過程完成之前有效。之后,設(shè)置將恢復(fù)為調(diào)用存儲過程時的值。這使個別的客戶端可以設(shè)置所需的選項,而不會影響存儲過程的邏輯。 說明 SQL Server 是將空字符串解釋為單個空格還是解釋為真正的空字符串,由兼容級別設(shè)置控制。如果兼容級別小于或等于 65,SQL Server 就將空字符串解釋為單個空格。如果兼容級別等于 70,則 SQL Server 將空字符串解釋為空字符串。有關(guān)更多信息,請參見 sp_dbcmptlevel。 獲得有關(guān)存儲過程的信息 若要顯示用來創(chuàng)建過程的文本,請在過程所在的數(shù)據(jù)庫中執(zhí)行 sp_helptext,并使用過程名作為參數(shù)。 說明 使用 ENCRYPTION 選項創(chuàng)建的存儲過程不能使用 sp_helptext 查看。 若要顯示有關(guān)過程引用的對象的報表,請使用 sp_depends。 若要為過程重命名,請使用 sp_rename。
引用對象 SQL Server 允許創(chuàng)建的存儲過程引用尚不存在的對象。在創(chuàng)建時,只進行語法檢查。執(zhí)行時,如果高速緩存中尚無有效的計劃,則編譯存儲過程以生成執(zhí)行計劃。只有在編譯過程中才解析存儲過程中引用的所有對象。因此,如果語法正確的存儲過程引用了不存在的對象,則仍可以成功創(chuàng)建,但在運行時將失敗,因為所引用的對象不存在。有關(guān)更多信息,請參見延遲名稱解析和編譯。
sql_statement 限制 除了 SET SHOWPLAN_TEXT 和 SET SHOWPLAN_ALL 之外(這兩個語句必須是批處理中僅有的語句),任何 SET 語句均可以在存儲過程內(nèi)部指定。所選擇的 SET 選項在存儲過程執(zhí)行過程中有效,之后恢復(fù)為原來的設(shè)置。 如果其他用戶要使用某個存儲過程,那么在該存儲過程內(nèi)部,一些語句使用的對象名必須使用對象所有者的名稱限定。這些語句包括: ALTER TABLE CREATE INDEX CREATE TABLE 所有 DBCC 語句 DROP TABLE DROP INDEX TRUNCATE TABLE UPDATE STATISTICS
示例 A. 使用帶有復(fù)雜 SELECT 語句的簡單過程 下面的存儲過程從四個表的聯(lián)接中返回所有作者(提供了姓名)、出版的書籍以及出版社。該存儲過程不使用任何參數(shù)。 USE pubs IF EXISTS (SELECT name FROM sysobjects WHERE name = 'au_info_all' AND type = 'P') DROP PROCEDURE au_info_all GO CREATE PROCEDURE au_info_all AS SELECT au_lname, au_fname, title, pub_name FROM authors a INNER JOIN titleauthor ta ON a.au_id = ta.au_id INNER JOIN titles t ON t.title_id = ta.title_id INNER JOIN publishers p ON t.pub_id = p.pub_id GO au_info_all 存儲過程可以通過以下方法執(zhí)行: EXECUTE au_info_all -- Or EXEC au_info_all 如果該過程是批處理中的第一條語句,則可使用: au_info_all B. 使用帶有參數(shù)的簡單過程 下面的存儲過程從四個表的聯(lián)接中只返回指定的作者(提供了姓名)、出版的書籍以及出版社。該存儲過程接受與傳遞的參數(shù)精確匹配的值。 USE pubs IF EXISTS (SELECT name FROM sysobjects WHERE name = 'au_info' AND type = 'P') DROP PROCEDURE au_info GO USE pubs GO CREATE PROCEDURE au_info @lastname varchar(40), @firstname varchar(20) AS SELECT au_lname, au_fname, title, pub_name FROM authors a INNER JOIN titleauthor ta ON a.au_id = ta.au_id INNER JOIN titles t ON t.title_id = ta.title_id INNER JOIN publishers p ON t.pub_id = p.pub_id WHERE au_fname = @firstname AND au_lname = @lastname GO au_info 存儲過程可以通過以下方法執(zhí)行: EXECUTE au_info 'Dull', 'Ann' -- Or EXECUTE au_info @lastname = 'Dull', @firstname = 'Ann' -- Or EXECUTE au_info @firstname = 'Ann', @lastname = 'Dull' -- Or EXEC au_info 'Dull', 'Ann' -- Or EXEC au_info @lastname = 'Dull', @firstname = 'Ann' -- Or EXEC au_info @firstname = 'Ann', @lastname = 'Dull' 如果該過程是批處理中的第一條語句,則可使用: au_info 'Dull', 'Ann' -- Or au_info @lastname = 'Dull', @firstname = 'Ann' -- Or au_info @firstname = 'Ann', @lastname = 'Dull' C. 使用帶有通配符參數(shù)的簡單過程 下面的存儲過程從四個表的聯(lián)接中只返回指定的作者(提供了姓名)、出版的書籍以及出版社。該存儲過程對傳遞的參數(shù)進行模式匹配,如果沒有提供參數(shù),則使用預(yù)設(shè)的默認(rèn)值。 USE pubs IF EXISTS (SELECT name FROM sysobjects WHERE name = 'au_info2' AND type = 'P') DROP PROCEDURE au_info2 GO USE pubs GO CREATE PROCEDURE au_info2 @lastname varchar(30) = 'D%', @firstname varchar(18) = '%' AS SELECT au_lname, au_fname, title, pub_name FROM authors a INNER JOIN titleauthor ta ON a.au_id = ta.au_id INNER JOIN titles t ON t.title_id = ta.title_id INNER JOIN publishers p ON t.pub_id = p.pub_id WHERE au_fname LIKE @firstname AND au_lname LIKE @lastname GO au_info2 存儲過程可以用多種組合執(zhí)行。下面只列出了部分組合: EXECUTE au_info2 -- Or EXECUTE au_info2 'Wh%' -- Or EXECUTE au_info2 @firstname = 'A%' -- Or EXECUTE au_info2 '[CK]ars[OE]n' -- Or EXECUTE au_info2 'Hunter', 'Sheryl' -- Or EXECUTE au_info2 'H%', 'S%' D. 使用 OUTPUT 參數(shù) OUTPUT 參數(shù)允許外部過程、批處理或多條 Transact-SQL 語句訪問在過程執(zhí)行期間設(shè)置的某個值。下面的示例創(chuàng)建一個存儲過程 (titles_sum),并使用一個可選的輸入?yún)?shù)和一個輸出參數(shù)。 首先,創(chuàng)建過程: USE pubs GO IF EXISTS(SELECT name FROM sysobjects WHERE name = 'titles_sum' AND type = 'P') DROP PROCEDURE titles_sum GO USE pubs GO CREATE PROCEDURE titles_sum @@TITLE varchar(40) = '%', @@SUM money OUTPUT AS SELECT 'Title Name' = title FROM titles WHERE title LIKE @@TITLE SELECT @@SUM = SUM(price) FROM titles WHERE title LIKE @@TITLE GO 接下來,將該 OUTPUT 參數(shù)用于控制流語言 說明 OUTPUT 變量必須在創(chuàng)建表和使用該變量時都進行定義。 參數(shù)名和變量名不一定要匹配,不過數(shù)據(jù)類型和參數(shù)位置必須匹配(除非使用 @@SUM = variable 形式)。 DECLARE @@TOTALCOST money EXECUTE titles_sum 'The%', @@TOTALCOST OUTPUT IF @@TOTALCOST 200 BEGIN PRINT ' ' PRINT 'All of these titles can be purchased for less than $200.' END ELSE SELECT 'The total cost of these titles is $' + RTRIM(CAST(@@TOTALCOST AS varchar(20))) 下面是結(jié)果集: Title Name ------------------------------------------------------------------------ The Busy Executive's Database Guide The Gourmet Microwave The Psychology of Computer Cooking (3 row(s) affected) Warning, null value eliminated from aggregate. All of these titles can be purchased for less than $200. E. 使用 OUTPUT 游標(biāo)參數(shù) OUTPUT 游標(biāo)參數(shù)用來將存儲過程的局部游標(biāo)傳遞回調(diào)用批處理、存儲過程或觸發(fā)器。 首先,創(chuàng)建以下過程,在 titles 表上聲明并打開一個游標(biāo): USE pubs IF EXISTS (SELECT name FROM sysobjects WHERE name = 'titles_cursor' and type = 'P') DROP PROCEDURE titles_cursor GO CREATE PROCEDURE titles_cursor @titles_cursor CURSOR VARYING OUTPUT AS SET @titles_cursor = CURSOR FORWARD_ONLY STATIC FOR SELECT * FROM titles OPEN @titles_cursor GO 接下來,執(zhí)行一個批處理,聲明一個局部游標(biāo)變量,執(zhí)行上述過程以將游標(biāo)賦值給局部變量,然后從該游標(biāo)提取行。 USE pubs GO DECLARE @MyCursor CURSOR EXEC titles_cursor @titles_cursor = @MyCursor OUTPUT WHILE (@@FETCH_STATUS = 0) BEGIN FETCH NEXT FROM @MyCursor END CLOSE @MyCursor DEALLOCATE @MyCursor GO F. 使用 WITH RECOMPILE 選項 如果為過程提供的參數(shù)不是典型的參數(shù),并且新的執(zhí)行計劃不應(yīng)高速緩存或存儲在內(nèi)存中,WITH RECOMPILE 子句會很有幫助。 USE pubs IF EXISTS (SELECT name FROM sysobjects WHERE name = 'titles_by_author' AND type = 'P') DROP PROCEDURE titles_by_author GO CREATE PROCEDURE titles_by_author @@LNAME_PATTERN varchar(30) = '%' WITH RECOMPILE AS SELECT RTRIM(au_fname) + ' ' + RTRIM(au_lname) AS 'Authors full name', title AS Title FROM authors a INNER JOIN titleauthor ta ON a.au_id = ta.au_id INNER JOIN titles t ON ta.title_id = t.title_id WHERE au_lname LIKE @@LNAME_PATTERN GO G. 使用 WITH ENCRYPTION 選項 WITH ENCRYPTION 子句對用戶隱藏存儲過程的文本。下例創(chuàng)建加密過程,使用 sp_helptext 系統(tǒng)存儲過程獲取關(guān)于加密過程的信息,然后嘗試直接從 syscomments 表中獲取關(guān)于該過程的信息。 IF EXISTS (SELECT name FROM sysobjects WHERE name = 'encrypt_this' AND type = 'P') DROP PROCEDURE encrypt_this GO USE pubs GO CREATE PROCEDURE encrypt_this WITH ENCRYPTION AS SELECT * FROM authors GO EXEC sp_helptext encrypt_this 下面是結(jié)果集: The object's comments have been encrypted. 接下來,選擇加密存儲過程內(nèi)容的標(biāo)識號和文本。 SELECT c.id, c.text FROM syscomments c INNER JOIN sysobjects o ON c.id = o.id WHERE o.name = 'encrypt_this'