周五了,祝大家周末愉快。
之前一直在寫SQL server的分享,今天再來個T-SQL編程中的存儲過程。
存儲過程
存儲過程(procedure)類似於C語言中的函數,用來執行管理任務或應用復雜的業務規則,存儲過程可以帶參數,也可以返回結果。
存儲過程可以包含數據操縱語句、變量、邏輯 控制語句等,比如:單個select語句,select語句塊,select語句與邏輯控制塊。
存儲過程優點:
執行速度更快
允許模塊化程序設計
提高系統安全性
減少網絡流通量
存儲過程分類
系統存儲過程
由系統定義,存放在master數據庫中
類似C語言中的系統函數
系統存儲過程的名稱都以“sp_”開頭或”xp_”開頭
用戶自定義存儲過程
由用戶在自己的數據庫中創建的存儲過程
類似C語言中的用戶自定義函數
常用的系統存儲過程如下表所示:
系統存儲過程 |
說明 |
sp_databases |
列出服務器上的所有數據庫。 |
sp_helpdb |
報告有關指定數據庫或所有數據庫的信息 |
sp_renamedb |
更改數據庫的名稱 |
sp_tables |
返回當前環境下可查詢的對象的列表 |
sp_columns |
回某個表列的信息 |
sp_help |
查看某個表的所有信息 |
sp_helpconstraint |
查看某個表的約束 |
sp_helpindex |
查看某個表的索引 |
sp_stored_procedures |
列出當前環境中的所有存儲過程。 |
sp_password |
添加或修改登錄帳戶的密碼。 |
sp_helptext |
顯示默認值、未加密的存儲過程、用戶定義的存儲過程、觸發器或視圖的實際文本。 |
存儲過程都是用exec調用,調用上述表中存儲過程如下:
EXEC sp_databases EXEC sp_renamedb 'Northwind','Northwind1' USE stuDB GO EXEC sp_tables EXEC sp_columns stuInfo EXEC sp_help stuInfo EXEC sp_helpconstraint stuInfo EXEC sp_helpindex stuMarks EXEC sp_helptext 'view_stuInfo_stuMarks' EXEC sp_stored_procedures
常用的擴展存儲過程:xp_cmdshell,可以執行DOS命令下的一些的操作,以文本行方式返回任何輸出
調用語法:
EXEC xp_cmdshell DOS命令 [NO_OUTPUT]
擴展存儲過程舉例:
USE master GO EXEC xp_cmdshell 'mkdir d:\bank', NO_OUTPUT IF EXISTS(SELECT * FROM sysdatabases WHERE name='bankDB') DROP DATABASE bankDB GO CREATE DATABASE bankDB ( … --創建數據庫語法略 ) GO EXEC xp_cmdshell 'dir D:\bank\' --查看文件
創建存儲過程
定義存儲過程的語法
CREATE PROC[EDURE] 存儲過程名 @參數1 數據類型 = 默認值 OUTPUT, …… , @參數n 數據類型 = 默認值 OUTPUT AS SQL語句 GO
存儲過程和C語言的函數一樣,參數可選,參數分為輸入參數、輸出參數,輸入參數允許有默認值。我們來看一個例子:
例:請創建存儲過程,查看本次考試平均分以及未通過考試的學員名單
CREATE PROCEDURE proc_stu AS DECLARE @writtenAvg float,@labAvg float SELECT @writtenAvg=AVG(writtenExam),@labAvg=AVG(labExam) FROM stuMarks print '筆試平均分:'+convert(varchar(5),@writtenAvg) print '機試平均分:'+convert(varchar(5),@labAvg) IF (@writtenAvg>70 AND @labAvg>70) print '本班考試成績:優秀' ELSE print '本班考試成績:較差' print '--------------------------------------------------' print ' 參加本次考試沒有通過的學員:' SELECT stuName,stuInfo.stuNo,writtenExam,labExam FROM stuInfo INNER JOIN stuMarks ON stuInfo.stuNo=stuMarks.stuNo WHERE writtenExam<60 OR labExam<60 GO
存儲過程的參數分為兩種:輸入參數和輸出參數
輸入參數
用於向存儲過程傳入值,類似C語言的按值傳遞
例:
CREATE PROCEDURE proc_stu @writtenPass int, @labPass int AS print '--------------------------------------------------' print ' 參加本次考試沒有通過的學員:' SELECT stuName,stuInfo.stuNo,writtenExam,labExam FROM stuInfo INNER JOIN stuMarks ON stuInfo.stuNo=stuMarks.stuNo WHERE writtenExam<@writtenPass OR labExam<@labPass GO
調用帶輸入參數存儲過程:
EXEC proc_stu 60,55 或者:EXEC proc_stu @labPass=55,@writtenPass=60
同同樣,還可以設置默認值,如下:
CREATE PROCEDURE proc_stu @writtenPass int=60, @labPass int=60 AS print '--------------------------------------------------' print ' 參加本次考試沒有通過的學員:' SELECT stuName,stuInfo.stuNo,writtenExam,labExam FROM stuInfo INNER JOIN stuMarks ON stuInfo.stuNo=stuMarks.stuNo WHERE writtenExam<@writtenPass OR labExam<@labPass GO
調用帶默認參數的存儲過程:
EXEC proc_stu --都采用默認值 EXEC proc_stu 64 --機試采用默認值 EXEC proc_stu 60,55 --都不采用默認值 或者:EXEC proc_stu @labPass=55
輸出參數
如果希望調用存儲過程后,返回一個或多個值,這時就需要使用輸出(OUTPUT)參數了
例:
CREATE PROCEDURE proc_stu @notpassSum int OUTPUT, @writtenPass int=60, @labPass int=60 AS …… SELECT stuName,stuInfo.stuNo,writtenExam, labExam FROM stuInfo INNER JOIN stuMarks ON stuInfo.stuNo=stuMarks.stuNo WHERE writtenExam<@writtenPass OR labExam<@labPass SELECT @notpassSum=COUNT(stuNo) FROM stuMarks WHERE writtenExam<@writtenPass OR labExam<@labPass GO
調用帶輸出參數的存儲過程
DECLARE @sum int EXEC proc_stu @sum OUTPUT ,64 print '--------------------------------------------------' IF @sum>=3 print '未通過人數:'+convert(varchar(5),@sum)+ '人, 超過60%,及格分數線還應下調' ELSE print '未通過人數:'+convert(varchar(5),@sum)+ '人,已控制在60%以下,及格分數線適中' GO
注意接收存儲過程返回值時必須加output關鍵字
刪除存儲過程:drop proc p_test4
處理存儲過程中的錯誤
RAISERROR 顯示用戶定義的錯誤信息時,可指定嚴重級別,設置系統變量@@ERROR,記錄所發生的錯誤等。
語法如下:
RAISERROR (msg_id | msg_str,severity,state WITH option[,...n]])
msg_id:在sysmessages系統表中指定用戶定義錯誤信息
msg_str:用戶定義的特定信息,最長255個字符
severity:定義嚴重性級別。用戶可使用的級別為0–18級
state:表示錯誤的狀態,1至127之間的值
option:指示是否將錯誤記錄到服務器錯誤日志中
例:
CREATE PROCEDURE proc_stu @notpassSum int OUTPUT, --輸出參數 @writtenPass int=60, --默認參數放后 @labPass int=60 --默認參數放后 AS IF (NOT @writtenPass BETWEEN 0 AND 100) OR (NOT @labPass BETWEEN 0 AND 100) BEGIN RAISERROR ('及格線錯誤,請指定0-100之間的分 數,統計中斷退出',16,1) RETURN ---立即返回,退出存儲過程 END …..其他語句同上例,略 GO
調用該存儲過程:
DECLARE @sum int, @t int EXEC proc_stu @sum OUTPUT ,604 --及格線設置為604出錯 SET @t=@@ERROR print '錯誤號:'+convert(varchar(5),@t ) IF @t<>0 RETURN --退出批處理,后續語句不再執行 print '--------------------------------------------------' IF @sum>=3 print '未通過人數:'+convert(varchar(5),@sum)+ '人,超過60%,及格分數線還應下調' ELSE print '未通過人數:'+convert(varchar(5),@sum)+ '人,已控制在60%以下,及格分數線適中' GO