表示最多可以指定 2.100 個參數的預留位置。
{RECOMPILE | ENCRYPTION | RECOMPILE, ENCRYPTION}
RECOMPILE 表明 SQL Server 不會緩衝該過程的計劃,該過程將在運行時重新編譯。在使用非典型值或臨時值而不希望覆蓋緩衝在記憶體中的執行計畫時,請使用 RECOMPILE 選項。
ENCRYPTION 表示 SQL Server 加密 syscomments 表中包含 CREATE PROCEDURE 語句文本的條目。使用 ENCRYPTION 可防止將過程作為 SQL Server 複製的一部分發布。
說明 在升級過程中,SQL Server 利用儲存在 syscomments 中的加密注釋來重新建立加密過程。
FOR REPLICATION
指定不能在訂閱伺服器上執行為複製建立的預存程序。.使用 FOR REPLICATION 選項建立的預存程序可用作預存程序篩選,且只能在複製過程中執行。本選項不能和 WITH RECOMPILE 選項一起使用。
AS
指定過程要執行的操作。
sql_statement
過程中要包含的任意數目和類型的 Transact-SQL 陳述式。但有一些限制。
是表示此過程可以包含多條 Transact-SQL 陳述式的預留位置。
注釋
預存程序的最大大小為 128 MB。
使用者定義的預存程序只能在當前資料庫中建立(暫存處理序除外,暫存處理序總是在 tempdb 中建立)。在單個批處理中,CREATE PROCEDURE 語句不能與其它 Transact-SQL 陳述式組合使用。
預設情況下,參數可為空白。如果傳遞 NULL 參數值並且該參數在 CREATE 或 ALTER TABLE 語句中使用,而該語句中引用的列又不允許使用 NULL,則 SQL Server 會產生一條錯誤資訊。為了防止向不允許使用 NULL 的列傳遞 NULL 參數值,應向過程中添加編程邏輯或為該列使用預設值(使用 CREATE 或 ALTER TABLE 的 DEFAULT 關鍵字)。
建議在預存程序的任何 CREATE TABLE 或 ALTER TABLE 語句中都為每列顯式指定 NULL 或 NOT NULL,例如在建立暫存資料表時。ANSI_DFLT_ON 和 ANSI_DFLT_OFF 選項控制 SQL Server 為列指派 NULL 或 NOT NULL 特性的方式(如果在 CREATE TABLE 或 ALTER TABLE 語句中沒有指定的話)。如果某個串連執行的預存程序對這些選項的設定與建立該過程的串連的設定不同,則為第二個串連建立的表列可能會有不同的為空白性,並且表現出不同的行為方式。如果為每個列顯式聲明了 NULL 或 NOT NULL,那麼將對所有執行該預存程序的串連使用相同的為空白性建立暫存資料表。
在建立或更改預存程序時,SQL Server 將儲存 SET QUOTED_IDENTIFIER 和 SET ANSI_NULLS 的設定。執行預存程序時,將使用這些原始設定。因此,所有用戶端工作階段的 SET QUOTED_IDENTIFIER 和 SET ANSI_NULLS 設定在執行預存程序時都將被忽略。在預存程序中出現的 SET QUOTED_IDENTIFIER 和 SET ANSI_NULLS 語句不影響預存程序的功能。
其它 SET 選項(例如 SET ARITHABORT、SET ANSI_WARNINGS 或 SET ANSI_PADDINGS)在建立或更改預存程序時不儲存。如果預存程序的邏輯取決於特定的設定,應在過程開頭添加一條 SET 語句,以確保設定正確。從預存程序中執行 SET 語句時,該設定只在預存程序完成之前有效。之後,設定將恢複為調用預存程序時的值。這使個別的用戶端可以設定所需的選項,而不會影響預存程序的邏輯。
說明 SQL Server 是將Null 字元串解釋為單個空格還是解釋為真正的Null 字元串,由相容層級設定控制。如果相容層級小於或等於 65,SQL Server 就將Null 字元串解釋為單個空格。如果相容層級等於 70,則 SQL Server 將Null 字元串解釋為空白字串。有關更多資訊,請參見 sp_dbcmptlevel。
獲得有關預存程序的資訊
若要顯示用來建立過程的文本,請在過程所在的資料庫中執行 sp_helptext,並使用過程名作為參數。
說明 使用 ENCRYPTION 選項建立的預存程序不能使用 sp_helptext 查看。
若要顯示有關過程引用的對象的報表,請使用 sp_depends。
若要為過程重新命名,請使用 sp_rename。
引用對象
SQL Server 允許建立的預存程序引用尚不存在的對象。在建立時,只進行語法檢查。執行時,如果快取中尚無有效計劃,則編譯預存程序以產生執行計畫。只有在編譯過程中才解析預存程序中引用的所有對象。因此,如果文法正確的預存程序引用了不存在的對象,則仍可以成功建立,但在運行時將失敗,因為所引用的對象不存在。有關更多資訊,請參見延遲名稱解析和編譯。
sql_statement 限制
除了 SET SHOWPLAN_TEXT 和 SET SHOWPLAN_ALL 之外(這兩個語句必須是批處理中僅有的語句),任何 SET 語句均可以在預存程序內部指定。所選擇的 SET 選項在預存程序執行過程中有效,之後恢複為原來的設定。
如果其他使用者要使用某個預存程序,那麼在該預存程序內部,一些語句使用的對象名必須使用對象所有者的名稱限定。這些語句包括:
ALTER TABLE
CREATE INDEX
CREATE TABLE
所有 DBCC 語句
DROP TABLE
DROP INDEX
TRUNCATE TABLE
UPDATE STATISTICS
樣本
A. 使用帶有複雜 SELECT 語句的簡單過程
下面的預存程序從四個表的聯結中返回所有作者(提供了姓名)、出版的書籍以及出版社。該預存程序不使用任何參數。
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 預存程序可以通過以下方法執行:
EXECUTE au_info_all
-- Or
EXEC au_info_all
如果該過程是批處理中的第一條語句,則可使用:
au_info_all
B. 使用帶有參數的簡單過程
下面的預存程序從四個表的聯結中只返回指定的作者(提供了姓名)、出版的書籍以及出版社。該預存程序接受與傳遞的參數精確匹配的值。
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 預存程序可以通過以下方法執行:
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. 使用帶有萬用字元參數的簡單過程
下面的預存程序從四個表的聯結中只返回指定的作者(提供了姓名)、出版的書籍以及出版社。該預存程序對傳遞的參數進行模式比對,如果沒有提供參數,則使用預設的預設值。
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 預存程序可以用多種組合執行。下面只列出了部分組合:
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 參數
OUTPUT 參數允許外部過程、批處理或多條 Transact-SQL 陳述式訪問在過程執行期間設定的某個值。下面的樣本建立一個預存程序 (titles_sum),並使用一個可選的輸入參數和一個輸出參數。
首先,建立過程:
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 參數用於流程控制語言
說明 OUTPUT 變數必須在建立表和使用該變數時都進行定義。
參數名和變數名不一定要匹配,不過資料類型和參數位置必須匹配(除非使用 @@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)))
下面是結果集:
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 遊標參數
OUTPUT 遊標參數用來將預存程序的局部遊標傳遞迴調用批處理、預存程序或觸發器。
首先,建立以下過程,在 titles 表上聲明並開啟一個遊標:
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
接下來,執行一個批處理,聲明一個局部遊標變數,執行上述過程以將遊標賦值給局部變數,然後從該遊標提取行。
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 選項
如果為過程提供的參數不是典型的參數,並且新的執行計畫不應快取或儲存在記憶體中,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 子句對使用者隱藏預存程序的文本。下例建立加密過程,使用 sp_helptext 系統預存程序擷取關於加密過程的資訊,然後嘗試直接從 syscomments 表中擷取關於該過程的資訊。
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
下面是結果集:
The object's comments have been encrypted.
接下來,選擇加密預存程序內容的標識號和文本。
SELECT c.id, c.text FROM syscomments c INNER JOIN sysobjects o ON c.id = o.id WHERE o.name = 'encrypt_this'