Transact-SQL中的預存程序,非常類似於Java語言中的方法,它可以重複調用。當預存程序執行一次後,可以將語句緩衝中,這樣下次執行的時候直接使用緩衝中的語句。這樣就可以提高預存程序的效能。
Ø 預存程序的概念
預存程序Procedure是一組為了完成特定功能的SQL語句集合,經編譯後儲存在資料庫中,使用者通過指定預存程序的名稱並給出參數來執行。
預存程序中可以包含邏輯控制語句和資料操縱語句,它可以接受參數、輸出參數、返回單個或多個結果集以及傳回值。
由於預存程序在建立時即在資料庫伺服器上進行了編譯並儲存在資料庫中,所以預存程序運行要比單個的SQL語句塊要快。同時由於在調用時只需用提供預存程序名和必要的參數資訊,所以在一定程度上也可以減少網路流量、簡單網路負擔。
1、 預存程序的優點
A、 預存程序允許標準組件式編程
預存程序建立後可以在程式中被多次調用執行,而不必重新編寫該預存程序的SQL語句。而且資料庫專業人員可以隨時對預存程序進行修改,但對應用程式原始碼卻毫無影響,從而極大的提高了程式的可移植性。
B、 預存程序能夠實現較快的執行速度
如果某一操作包含大量的T-SQL語句代碼,分別被多次執行,那麼預存程序要比批處理的執行速度快得多。因為預存程序是先行編譯的,在首次運行一個預存程序時,查詢最佳化工具對其進行分析、最佳化,並給出最終被存在系統資料表中的儲存計劃。而批處理的T-SQL語句每次運行都需要先行編譯和最佳化,所以速度就要慢一些。
C、 預存程序減輕網路流量
對於同一個針對資料庫物件的操作,如果這一操作所涉及到的T-SQL語句被組織成一預存程序,那麼當在客戶機上調用該預存程序時,網路中傳遞的只是該調用語句,否則將會是多條SQL語句。從而減輕了網路流量,降低了網路負載。
D、 預存程序可被作為一種安全機制來充分利用
系統管理員可以對執行的某一個預存程序進行許可權限制,從而能夠實現對某些資料訪問的限制,避免非授權使用者對資料的訪問,保證資料的安全。
Ø 系統預存程序
系統預存程序是系統建立的預存程序,目的在於能夠方便的從系統資料表中查詢資訊或完成與更新資料庫表相關的管理工作或其他的系統管理任務。系統預存程序主要儲存在master資料庫中,以“sp”底線開頭的預存程序。儘管這些系統預存程序在master資料庫中,但我們在其他資料庫還是可以調用系統預存程序。有一些系統預存程序會在建立新的資料庫的時候被自動建立在當前資料庫中。
常用系統預存程序有:
複製代碼 代碼如下:
exec sp_databases; --查看資料庫
exec sp_tables; --查看錶
exec sp_columns student;--查看列
exec sp_helpIndex student;--查看索引
exec sp_helpConstraint student;--約束
exec sp_stored_procedures;
exec sp_helptext 'sp_stored_procedures';--查看預存程序建立、定義語句
exec sp_rename student, stuInfo;--修改表、索引、列的名稱
exec sp_renamedb myTempDB, myDB;--更改資料庫名稱
exec sp_defaultdb 'master', 'myDB';--更改登入名稱的預設資料庫
exec sp_helpdb;--資料庫協助,查詢資料庫資訊
exec sp_helpdb master;
系統預存程序樣本:
--表重新命名
exec sp_rename 'stu', 'stud';select * from stud;
--列重新命名
exec sp_rename 'stud.name', 'sName', 'column';exec sp_help 'stud';
--重新命名索引
exec sp_rename N'student.idx_cid', N'idx_cidd', N'index';exec sp_help 'student';
--查詢所有預存程序
select * from sys.objects where type = 'P';select * from sys.objects where type_desc like '%pro%' and name like 'sp%';
Ø 使用者自訂預存程序
1、 建立文法
create proc | procedure pro_name
[{@參數資料類型} [=預設值] [output],
{@參數資料類型} [=預設值] [output],
....
]
as
SQL_statements
2、 建立不帶參數預存程序
--建立預存程序
if (exists (select * from sys.objects where name = 'proc_get_student')) drop proc proc_get_studentgocreate proc proc_get_studentas select * from student;
--調用、執行預存程序
3、 修改預存程序
--修改預存程序
alter proc proc_get_studentasselect * from student;
4、 帶參預存程序
--帶參預存程序
if (object_id('proc_find_stu', 'P') is not null) drop proc proc_find_stugocreate proc proc_find_stu(@startId int, @endId int)as select * from student where id between @startId and @endIdgoexec proc_find_stu 2, 4;
5、 帶萬用字元參數預存程序
--帶萬用字元參數預存程序
if (object_id('proc_findStudentByName', 'P') is not null) drop proc proc_findStudentByNamegocreate proc proc_findStudentByName(@name varchar(20) = '%j%', @nextName varchar(20) = '%')as select * from student where name like @name and name like @nextName;goexec proc_findStudentByName;exec proc_findStudentByName '%o%', 't%';
6、 帶輸出參數預存程序
if (object_id('proc_getStudentRecord', 'P') is not null) drop proc proc_getStudentRecordgocreate proc proc_getStudentRecord( @id int, --預設輸入參數 @name varchar(20) out, --輸出參數 @age varchar(20) output--輸入輸出參數)as select @name = name, @age = age from student where id = @id and sex = @age;go-- declare @id int, @name varchar(20), @temp varchar(20);set @id = 7; set @temp = 1;exec proc_getStudentRecord @id, @name out, @temp output;select @name, @temp;print @name + '#' + @temp;
7、 不緩衝預存程序
--WITH RECOMPILE 不緩衝
if (object_id('proc_temp', 'P') is not null) drop proc proc_tempgocreate proc proc_tempwith recompileas select * from student;goexec proc_temp;
8、 加密預存程序
--加密WITH ENCRYPTION
if (object_id('proc_temp_encryption', 'P') is not null) drop proc proc_temp_encryptiongocreate proc proc_temp_encryptionwith encryptionas select * from student;goexec proc_temp_encryption;exec sp_helptext 'proc_temp';exec sp_helptext 'proc_temp_encryption';
9、 帶遊標參數預存程序
if (object_id('proc_cursor', 'P') is not null) drop proc proc_cursorgocreate proc proc_cursor @cur cursor varying outputas set @cur = cursor forward_only static for select id, name, age from student; open @cur;go--調用declare @exec_cur cursor;declare @id int, @name varchar(20), @age int;exec proc_cursor @cur = @exec_cur output;--調用預存程序fetch next from @exec_cur into @id, @name, @age;while (@@fetch_status = 0)begin fetch next from @exec_cur into @id, @name, @age; print 'id: ' + convert(varchar, @id) + ', name: ' + @name + ', age: ' + convert(char, @age);endclose @exec_cur;deallocate @exec_cur;--刪除遊標
10、 分頁預存程序
---預存程序、row_number完成分頁
if (object_id('pro_page', 'P') is not null) drop proc proc_cursorgocreate proc pro_page @startIndex int, @endIndex intas select count(*) from product; select * from ( select row_number() over(order by pid) as rowId, * from product ) temp where temp.rowId between @startIndex and @endIndexgo--drop proc pro_pageexec pro_page 1, 4----分頁預存程序if (object_id('pro_page', 'P') is not null) drop proc pro_stugocreate procedure pro_stu( @pageIndex int, @pageSize int)as declare @startRow int, @endRow int set @startRow = (@pageIndex - 1) * @pageSize +1 set @endRow = @startRow + @pageSize -1 select * from ( select *, row_number() over (order by id asc) as number from student ) t where t.number between @startRow and @endRow;exec pro_stu 2, 2;
Ø Raiserror
Raiserror返回使用者定義的錯誤資訊,可以指定嚴重層級,設定系統變數記錄所發生的錯誤。
文法如下:
Raiserror({msg_id | msg_str | @local_variable}
{, severity, state}
[,argument[,…n]]
[with option[,…n]]
)
# msg_id:在sysmessages系統資料表中指定的使用者定義錯誤資訊
# msg_str:使用者定義的資訊,資訊最大長度在2047個字元。
# severity:使用者定義與該訊息關聯的嚴重層級。當使用msg_id引發使用sp_addmessage建立的使用者定義訊息時,raiserror上指定嚴重性將覆蓋sp_addmessage中定義的嚴重性。
任何使用者可以指定0-18直接的嚴重層級。只有sysadmin固定伺服器角色常用或具有alter trace許可權的使用者才能指定19-25直接的嚴重層級。19-25之間的安全層級需要使用with log選項。
# state:介於1至127直接的任何整數。State預設值是1。
raiserror('is error', 16, 1);
select * from sys.messages;
--使用sysmessages中定義的訊息
raiserror(33003, 16, 1);
raiserror(33006, 16, 1);
以上所述就是本文的全部內容了,希望大家能夠喜歡。