SQL Server 儲存過程

taogchan發表於2015-01-20

SQL Server 儲存過程

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_student go create proc proc_get_student as select * from student;

--呼叫、執行儲存過程 exec proc_get_student;

   3、 修改儲存過程

--修改儲存過程 alter proc proc_get_student as select * from student;

   4、 帶參儲存過程

--帶參儲存過程 if (object_id('proc_find_stu', 'P') is not null) drop proc proc_find_stu go create proc proc_find_stu(@startId int, @endId int) as select * from student where id between @startId and @endId go exec proc_find_stu 2, 4;

   5、 帶萬用字元引數儲存過程

--帶萬用字元引數儲存過程 if (object_id('proc_findStudentByName', 'P') is not null) drop proc proc_findStudentByName go create proc proc_findStudentByName(@name varchar(20) = '%j%', @nextName varchar(20) = '%') as select * from student where name like @name and name like @nextName; go exec proc_findStudentByName; exec proc_findStudentByName '%o%', 't%';

   6、 帶輸出引數儲存過程

if (object_id('proc_getStudentRecord', 'P') is not null) drop proc proc_getStudentRecord go create 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_temp go create proc proc_temp with recompile as select * from student; go exec proc_temp;

   8、 加密儲存過程

--加密WITH ENCRYPTION if (object_id('proc_temp_encryption', 'P') is not null) drop proc proc_temp_encryption go create proc proc_temp_encryption with encryption as select * from student; go exec 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_cursor go create proc proc_cursor
    @cur cursor varying output as 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); end close @exec_cur; deallocate @exec_cur;--刪除遊標


   10、 分頁儲存過程

---儲存過程、row_number完成分頁 if (object_id('pro_page', 'P') is not null) drop proc proc_cursor go create proc pro_page
    @startIndex int,
    @endIndex int as select count(*) from product
; select * from ( select row_number() over(order by pid) as rowId, * from product 
    ) temp where temp.rowId between @startIndex and @endIndex go --drop proc pro_page exec pro_page 1, 4 -- --分頁儲存過程 if (object_id('pro_page', 'P') is not null) drop proc pro_stu go create 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);

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22392018/viewspace-1408454/,如需轉載,請註明出處,否則將追究法律責任。

相關文章