1、設計存儲過程
幾乎任何可寫成批處理的 Transact-SQL 代碼都可用于創(chuàng)建存儲過程。
2、存儲過程的設計規(guī)則
存儲過程的設計規(guī)則包括:
- CREATE PROCEDURE 定義本身可包括除下列 CREATE 語句以外的任何數(shù)量和類型的 SQL 語句,存儲過程中的任意地方都不能使用下列語句:
CREATE DEFAULT |
CREATE TRIGGER |
CREATE PROCEDURE |
CREATE VIEW |
CREATE RULE |
|
- 可在存儲過程中創(chuàng)建其它數(shù)據(jù)庫對象。可以引用在同一存儲過程中創(chuàng)建的對象,前提是在創(chuàng)建對象后再引用對象。
- 可以在存儲過程內(nèi)引用臨時表。
- 如果在存儲過程內(nèi)創(chuàng)建本地臨時表,則該臨時表僅為該存儲過程而存在;退出該存儲過程后,臨時表即會消失。
- 如果執(zhí)行調(diào)用其它存儲過程的存儲過程,那么被調(diào)用存儲過程可以訪問由第一個存儲過程創(chuàng)建的、包括臨時表在內(nèi)的所有對象。
- 如果執(zhí)行在遠程 Microsoft® SQL Server™ 2000 實例上進行更改的遠程存儲過程,則不能回滾這些更改。遠程存儲過程不參與事務處理。
- 存儲過程中參數(shù)的最大數(shù)目為 2100。
- 存儲過程中局部變量的最大數(shù)目僅受可用內(nèi)存的限制。
- 根據(jù)可用內(nèi)存的不同,存儲過程的最大大小可達 128 MB。
3、限定存儲過程內(nèi)的名稱
在存儲過程內(nèi)部,如果用于諸如 SELECT 或 INSERT 這樣的語句的對象名沒有限定用戶,那么用戶將默認為該存儲過程的所有者。在存儲過程內(nèi)部,如果創(chuàng)建存儲過程的用戶沒有限定 SELECT、INSERT、UPDATE 或 DELETE 語句中引用的表名,那么通過該存儲過程對這些表進行的訪問將默認地受到該過程的創(chuàng)建者權(quán)限的限制。
如果有其他用戶要使用存儲過程,則用于語句 ALTER TABLE、CREATE TABLE、DROP TABLE、TRUNCATE TABLE、CREATE INDEX、DROP INDEX、UPDATE STATISTICS 和 DBCC 的對象名必須用該對象所有者的名稱限定。例如,Mary 擁有表 marytab,如果她希望其他用戶能夠執(zhí)行使用該表的存儲過程,必須在該表用于上述某一條語句時對其表名進行限定。
此規(guī)則是必需的,因為運行存儲過程時將解析對象的名稱。如果未限定 marytab,而 John 試圖執(zhí)行該過程,SQL Server 將查找 John 所擁有的名為 marytab 的表。
4、加密過程定義
如果要創(chuàng)建存儲過程,并且希望確保其他用戶無法查看該過程的定義,那么可以使用 WITH ENCRYPTION 子句。這樣,過程定義將以不可讀的形式存儲。
存儲過程一旦加密其定義即無法解密,任何人(包括存儲過程的所有者或系統(tǒng)管理員)都將無法查看存儲過程定義。
5、SET 語句選項
當 ODBC 應用程序與 SQL Server 連接時,服務器將自動設置會話的下列選項:
- SET QUOTED_IDENTIFIER ON
- SET TEXTSIZE 2147483647
- SET ANSI_DEFAULTS ON
- SET CURSOR_CLOSE_ON_COMMIT OFF
- SET IMPLICIT_TRANSACTIONS OFF
這些設置將提高 ODBC 應用程序的可移植性。由于基于 DB-Library 的應用程序通常不設置這些選項,所以應在上述所列 SET 選項打開和關閉的情況下都對存儲過程進行測試。這樣可確保存儲過程始終能正確工作,而不管特定的連接在喚醒調(diào)用該存儲過程時可能設置的選項。需要特別設置其中一個選項的存儲過程,應在開始該存儲過程時發(fā)出一條 SET 語句。此 SET 語句將只對該存儲過程的執(zhí)行保持有效,當該存儲過程結(jié)束時,將恢復原設置。
示例
A. 創(chuàng)建使用參數(shù)的存儲過程
下例創(chuàng)建一個在 pubs 數(shù)據(jù)庫中很有用的存儲過程。給出一個作者的姓和名,該存儲過程將顯示該作者的每本書的標題和出版商。
CREATE PROC au_info @lastname varchar(40), @firstname varchar(20)
AS
SELECT au_lname, au_fname, title, pub_name
FROM authors INNER JOIN titleauthor ON authors.au_id = titleauthor.au_id
JOIN titles ON titleauthor.title_id = titles.title_id
JOIN publishers ON titles.pub_id = publishers.pub_id
WHERE au_fname = @firstname
AND au_lname = @lastname
GO

將出現(xiàn)一條說明該命令未返回任何數(shù)據(jù)也未返回任何行的消息,這表示已創(chuàng)建該存儲過程。
現(xiàn)在執(zhí)行 au_info 存儲過程:
EXECUTE au_info Ringer, Anne
GO
下面是結(jié)果集:
au_lname |
au_fname |
title |
pub_name |
--------- |
--------- |
--------------------- |
---------------- |
Ringer |
Anne |
The Gourmet Microwave |
Binnet & Hardley |
Ringer |
Anne |
Is Anger the Enemy? |
New Moon Books |
(2 row(s) affected)
B. 創(chuàng)建使用參數(shù)默認值的存儲過程
下例創(chuàng)建一個存儲過程 pub_info2,該存儲過程顯示作為參數(shù)給出的出版商所出版的某本書的作者姓名。如果未提供出版商的名稱,該存儲過程將顯示由 Algodata Infosystems 出版的書籍的作者。
CREATE PROC pub_info2 @pubname varchar(40) = 'Algodata Infosystems'
AS
SELECT au_lname, au_fname, pub_name
FROM authors a INNER JOIN titleauthor ta ON a.au_id = ta.au_id
JOIN titles t ON ta.title_id = t.title_id
JOIN publishers p ON t.pub_id = p.pub_id
WHERE @pubname = p.pub_name

執(zhí)行未指定參數(shù)的 pub_info2:
EXECUTE pub_info2
GO
下面是結(jié)果集:
au_lname |
au_fname |
pub_name |
---------------- |
---------------- |
-------------------- |
Green |
Marjorie |
Algodata Infosystems |
Bennet |
Abraham |
Algodata Infosystems |
O'Leary |
Michael |
Algodata Infosystems |
MacFeather |
Stearns |
Algodata Infosystems |
Straight |
Dean |
Algodata Infosystems |
Carson |
Cheryl |
Algodata Infosystems |
Dull |
Ann |
Algodata Infosystems |
Hunter |
Sheryl |
Algodata Infosystems |
Locksley |
Charlene |
Algodata Infosystems |
(9 row(s) affected)
C. 執(zhí)行用顯式值替代參數(shù)默認值的存儲過程
在下例中,存儲過程 showind2 的 @table 參數(shù)默認值是 titles。
CREATE PROC showind2 @table varchar(30) = 'titles'
AS
SELECT TABLE_NAME = sysobjects.name,
INDEX_NAME = sysindexes.name, INDEX_ID = indid
FROM sysindexes INNER JOIN sysobjects ON sysobjects.id = sysindexes.id
WHERE sysobjects.name = @table

列標題(例如,TABLE_NAME)可使結(jié)果更具可讀性。下面是該存儲過程顯示的 authors 表的情況:
EXECUTE showind2 authors
GO
TABLE_NAME |
INDEX_NAME |
INDEX_ID |
---------- |
---------- |
---------- |
authors |
UPKCL_auidind |
1 |
authors |
aunmind |
2 |
(2 row(s) affected)
如果用戶未提供值,則 SQL Server 將使用默認表 titles:
EXECUTE showind2
GO
下面是結(jié)果集:
TABLE_NAME |
INDEX_NAME |
INDEX_ID |
---------- |
---------- |
---------- |
titles |
UPKCL_titleidind |
1 |
titles |
titleind |
2 |
(2 row(s) affected)
D. 使用參數(shù)默認值 NULL 創(chuàng)建存儲過程
參數(shù)默認值可以是 NULL 值。在這種情況下,如果未提供參數(shù),則 SQL Server 將根據(jù)存儲過程的其它語句執(zhí)行存儲過程。不會顯示錯誤信息。
過程定義還可指定當不給出參數(shù)時要采取的其它某種措施。例如:
CREATE PROC showind3 @table varchar(30) = NULL
AS IF @table IS NULL
PRINT 'Give a table name'
ELSE
SELECT TABLE_NAME = sysobjects.name,
INDEX_NAME = sysindexes.name, INDEX_ID = indid
FROM sysindexes INNER JOIN sysobjects
ON sysobjects.id = sysindexes.id
WHERE sysobjects.name = @table

E. 使用包含通配符的參數(shù)默認值創(chuàng)建存儲過程
如果存儲過程將參數(shù)用于 LIKE 關鍵字,那么默認值可包括通配符(%、_、[] 和 [^])。例如,可將 showind 修改為當不提供參數(shù)時顯示有關系統(tǒng)表的信息:
CREATE PROC showind4 @table varchar(30) = 'sys%'
AS SELECT TABLE_NAME = sysobjects.name,
INDEX_NAME = sysindexes.name, INDEX_ID = indid
FROM sysindexes INNER JOIN sysobjects
ON sysobjects.id = sysindexes.id
WHERE sysobjects.name LIKE @table

在存儲過程 au_info 的下列變化形式中,兩個參數(shù)都有帶通配符的默認值:
CREATE PROC au_info2 @lastname varchar(30) = 'D%',
@firstname varchar(18) = '%'
AS
SELECT au_lname, au_fname, title, pub_name
FROM authors INNER JOIN titleauthor ON authors.au_id = titleauthor.au_id
JOIN titles ON titleauthor.title_id = titles.title_id
JOIN publishers ON titles.pub_id = publishers.pub_id
WHERE au_fname LIKE @firstname
AND au_lname LIKE @lastname
如果執(zhí)行 au_info2 時不指定參數(shù),將顯示姓以字母 D 開頭的所有作者:
EXECUTE au_info2
GO
下面是結(jié)果集:
au_lname |
au_fname |
title |
pub_name |
-------- |
-------- |
--------------------- |
------------------- |
Dull |
Ann |
Secrets of Silicon Val |
Algodata Infosystems |
del Castillo |
Innes |
Silicon Val Gastrono |
Binnet & Hardley |
DeFrance |
Michel |
The Gourmet Microwave |
Binnet & Hardley |
(3 row(s) affected)
下例在兩個參數(shù)的默認值已定義的情況下,省略了第二個參數(shù),因此可找到姓為 Ringer 的所有作者的書和出版商:
EXECUTE au_info2 Ringer
GO
au_lname |
au_fname |
title |
pub_name |
--------- |
--------- |
---------------------- |
---------------- |
Ringer |
Anne |
The Gourmet Microwave |
Binnet & Hardley |
Ringer |
Anne |
Is Anger the Enemy? |
New Moon Books |
Ringer |
Albert |
Is Anger the Enemy? |
New Moon Books |
Ringer |
Albert |
Life Without Fear |
New Moon Books |
(4 row(s) affected)