Sybase 的存儲過程是集中存儲在 SQL Server 中的預先定義且已經編譯好的事務。存儲過程由SQL語句和流程控制語句組成。它的功能包括:接受參數、調用另一過程、返回一個狀態值給調用過程或批處理、指示調用成功或失敗、返回若干個參數值給調用過程或批處理、爲調用者提供動態結果、在遠程SQL Server中運行等。
存儲過程的性能特點如下:
·存儲過程是預編譯過的,這就意味着它與普通的 SQL 語句或批處理的 SQL 語句不同,當首次運行一個存儲過程時,SQL Server 的查詢處理器對其進行分析,在排除了語法錯誤之後形成存儲在系統中的可執行方案。由於查詢處理的大部分工作已經完成,所以存儲過程執行速度很快。
·存儲過程和待處理的數據都放在同一臺運行 SQL Server 的計算機上,使用存儲過程查詢當地的數據,效率自然很高。
·存儲過程一般多由 Client 端通過存儲過程的名字進行調用,即跨網傳送的只是存儲過程的名字及少量的參數(如果有的話),而不是構成存儲過程的許多 SQL 語句,因此可以減少網絡傳輸量,加快系統響應速度。
·存儲過程還有着如同 C 語言子函數那樣的被調用和返回值的方便特性。
所以,存儲過程大大增強了 SQL 語言的功能、效率和靈活性。掌握和應用好存儲過程,對進一步發揮Sybase 數據庫系統的強大功能有着重要的意義。
存儲過程的語法規則
建立存儲過程的語法規則爲:
CREATE PROCedure[owner.]procedurename[;number]
[[(]@parameter_name datatype[=default][OUTput]
[,@parameter_name datatype[=default][OUTput]]...[)]]
[WITH RECOMPILE]
AS SQL_statements
使用存儲過程的語法規則爲:
[EXECute][@return-status=]
[[[server.]database.]owner.]procedurename[;number]
[[@parameter_name=]value|[@parameter_name=]@varialbe[OUTput]
[,[@parameter_name=]value|[@parameter_name=]@variable[OUTput]...]]
[WITH RECOMPILE]
[page]下面簡要介紹這兩個命令的常用選項以及建立和使用存儲過程的要點,關於選項的更爲詳細的說明請參考有關手冊。
·[[[server.]database.]owner.]procedure_name:存儲過程的名字。
·@parameter_name datatype[=default][OUTput]:形式參數(形參)的名稱、類型。
dfault是賦予的缺省值(可選),OUTput指定本參數爲輸出參數(可選)。形參是存儲過程中的自變量,可以有多個,名字必須以@打頭,最長30個字符。
·SQL_statements:定義存儲過程功能的 SQL 語句。
·@return_status:接受存儲過程返回狀態值的變量。
·[@parameter_name=]value:實際參數(實參),@parameter_name 爲實參的名稱(可選)。如果某個實參以@parameter_name=value提供,那麼隨後的實參也都要採用這一形式提供。
·[@parameter_name=]@varialbe[OUTput]:將變量 @varialbe 中的值作爲實參傳遞給形參@parameter_name(可選),如果變量 @varialbe 是用來接受返回的參數值,則選項 OUTput 不可缺少。
存儲過程的建立和使用,我們將通過幾個例子進行介紹。
假設有一個用下述語句生成的技能工資表 RS-LS-GZ-JiNeng:
create table RS_LS_GZ_JiNeng /*技能工資表*/
(GeRen_id char(4), /*個人代碼 */
RiQi smalldatetime, /*執行日期 */
YuanYin_id char(1) null, /*變動原因代碼 */
JinE smallmoney) /*技能工資金額 */
該表存儲着某單位員工多年來技能工資的歷史檔案。
例1、如果要查詢全體員工的技能工資變動歷史,則可先建立一個存儲過程 p-RsGz-JiNeg-All:
create procedure p_RsGz_JiNeng_All as
select *
from RS_LS_GZ_JiNeng
order by GeRenid,RiQi
然後用批處理語句調用存儲過程 p_RsGz_JiNeng_All 進行查詢:
execute p_RsGz_JiNeng_All
本例只顯示查詢到的數據,無輸入、輸出參量,是最簡單的一個存儲過程。
例2、如果要查詢某人技能工資的變動歷史,可建立另一個存儲過程 p_RsGz_JiNeng:
create procedure p_RsGz_JiNeng @c_GeRenId char(4)
as
select *from RS_LS_GZ_JiNeng
where GeRen_id=@c_GeRenId
order by RiQi
之後用批處理語句調用存儲過程 p_Rs_Gz_JiNeng 進行查詢:
declare @GeRenId char(4)
select @GeRenId="0135" /*設要查詢員工的個人代碼爲 "0135" */
execute p_RsGz_JeNeng @c_GeRenId=@GeRenId
存儲過程 p_RsGz_JiNeng 中定義了一個形參 @c_GeRenId,是字符型變量。在調用該過程的批處理中,既可以用具體的值也可以用變量作爲實參。
用變量作實參(如本例)時,必須用 del are 語句加以說明。值得注意的是,在批處理的調用過程語句中,@c_GeRenId=@GeRenId 中的 @ c_GeRenId 是存儲過程 p_RsGz_JiNeng 中的形參名,不是批處理中的變量,所以不能將它列入 declare 語句的變量單中。
例3/如果要計算當月工資,就必須從工資歷史中查出員工距離當前最近的一次技能工資變動的結果:
create procedure p_RsGz_JiNeng_Slt
(@c_GeRenId char(4),@sm_JinE smallmoney output)
as
select @sm_JinE=JinE
from RS_LS_GZ_JiNeng
where RiQi=(select max(RiQi)
from RS_LS_GZ_JiNeng
where GeRenid=@c-GeRenId) /*找出歷史記錄中距離當前最近的日期*/
調用存儲過程 p_RsGz_JiNeng_Slt 進行查詢:
declare @GeRenId char(4),@JinE smallmoney
select @GeRenid="0135"/*設要查詢員工的個人代碼爲 "0135"*/
select @JinE=0
execute p_RsGz_JiNeng_slt @c_GeRenId=@GeRenId,@sm_JinE=@ JinE output
這裏,變量 @JinE 用來存儲過程形參 @sm_JinE 傳回的金額。在調用過程語句中,@sm_JiE = @JinE output 中的 output 不可省略。否則變量 @JinE 將得不到形參傳回的數值而始終爲零(等於初值)。
例4、查到了個人代碼爲 "0135" 員工的技能工資就顯示其歷史紀錄,查不到則顯示一條出錯信息。
create procedure p_RsGz_JiNeng_Rtn
@c_GeRenId char(4)
as
declare @ErrCode smallint
select @ErrCode=0
if exists(select* from RS-LS-GZ-JiNeng
where GeRenid=@c-GeRenId)
begin
select *
from RS_LS_GZ_JiNeng
whrer GeRen_id=@c_GeRenId
order by RiQi
return @ErrCode
end
esle
begin
select @ErrCode=1
return @ErrCode
end
調用存儲過程 p_RsGz_JiNeng_Rtn:
declare @GeRenId char(4),@RtnCode smallint
select @GeRenId="0135"
select @RtnCode=0
execute @RtnCode=p_RsGz_JiNeng_Rtn @c_GeRenId=@GeRenId
if @RtnCode=1
print"No this one!"
存儲過程 p_RsGz_JiNeng_Rtn 向調用者返回一個存儲在變量@ErrCode裏的值,這個值被稱爲狀態值,它向調用者反映存儲過程執行的成敗狀態。在本例中,如果查不到指定員工技能工資的任何記錄時,就認爲"查無此人",返回出錯狀態值 1。否則返回成功狀態值 0。
調用過程的批處理語句使用變量 @RtnCode 存儲返回的狀態值,一旦檢出存儲過程 p_RsG_ JiNeng_Rtn 返回了錯誤標誌 (@RtnCode=1),就顯示一條信息 "No this one!"。
小結
上述四個例子簡要介紹了存儲過程常用的幾種形式,從中我們已經可以領略到它的編程特色以及使用上的靈活性和方便性。
雖然上述例子在調用存儲過程時都是用 SQL 的批處理語句實現的,但並不意味着這是唯一的方法。例如在存儲過程中調用存儲過程(即所謂過程嵌套)的現象就很常見。另外在其它 Sybase 數據庫開發系統 (如PowerBuilder)的 script 語句中調用 Sybase 的存儲過程也非常普遍。