SQL Server儲存過程的使用
儲存過程概述
簡單來說,儲存過程就是一條或者多條sql語句的集合,可視為批處理檔案,但是其作用不僅限於批處理。
基本概念:
SQL Server中的儲存過程是使用T_SQL編寫的程式碼段。它的目的在於能夠方便的從系統表中查詢資訊,
或者完成與更新資料庫表相關的管理任務和其他的系統管理任務.T_SQL語句是SQL Server資料庫與應用程式之間的程式設計介面。
儲存過程就是SQL Server為了實現特定任務,而將一些需要多次呼叫的固定操作語句編寫成程式段,這些程式段儲存在伺服器上,
有資料庫伺服器通過程式來呼叫。
- 為什麼要使用儲存過程?不使用儲存過程會怎麼樣?
在很多情況下,一些程式碼會被開發者重複編寫多次,如果每次都編寫相同功能的程式碼,不但繁瑣,而且容易出錯,
如果不使用的話,SQL Server逐條的執行語句會降低系統的執行效率。
- 儲存過程的優點:
- 儲存過程加快系統執行速度,儲存過程只在建立時編譯,以後每次執行時不需要重新編譯。
- 儲存過程可以封裝複雜的資料庫操作,簡化操作流程,例如對多個表的更新,刪除等。
- 可實現模組化的程式設計,儲存過程可以多次呼叫,提供統一的資料庫訪問介面,改進應用程式的可維護性。
- 儲存過程可以增加程式碼的安全性,對於使用者不能直接操作儲存過程中引用的物件,SQL Server可以設定使用者對指定儲存過程的執行許可權。
- 儲存過程的缺點:
- 資料庫移植不方便,儲存過程依賴與資料庫管理系統, SQL Server 儲存過程中封裝的操作程式碼不能直接移植到其他的資料庫管理系統中。
- 不支援面向物件的設計,
- 程式碼可讀性差,不易維護。不支援叢集。
儲存過程分類
- 系統儲存過程
系統儲存過程是 SQL Server系統自身提供的儲存過程,可以作為命令執行各種操作。
系統儲存過程主要用來從系統表中獲取資訊,使用系統儲存過程完成資料庫伺服器的管理工作,為系統管理員提供幫助,
為使用者檢視資料庫物件提供方便,系統儲存過程位於資料庫伺服器中,並且以sp_開頭
系統儲存過程建立並存放在與系統資料庫master中,一些系統儲存過程只能由系統管理員使用,而有些系統儲存過程通過授權可以被其它使用者所使用。
- 使用者儲存過程(自定義儲存過程)
自定義儲存過程即使用者使用T_SQL語句編寫的、為了實現某一特定業務需求,在使用者資料庫中編寫的T_SQL語句集合,
自定義儲存過程可以接受輸入引數、向客戶端返回結果和資訊,返回輸出引數等。建立自定義儲存過程時,
儲存過程名前加上"##"表示建立了一個全域性的臨時儲存過程;儲存過程前面加上"#"時,表示建立的區域性臨時儲存過程。
區域性臨時儲存過程只能在建立它的回話中使用,會話結束時,將被刪除。這兩種儲存過程都儲存在tempdb資料庫中。
T_SQL:儲存過程是值儲存的T_SQL語句集合,可以接受和返回使用者提供的引數,儲存過程也可能從資料庫向客戶端應用程式返回資料。
建立儲存過程
1 use bookdb; 2 --建立測試books表 3 create table books ( 4 book_id int identity(1,1) primary key, 5 book_name varchar(20), 6 book_price float, 7 book_author varchar(10) 8 ); 9 --插入測試資料 10 insert into books (book_name,book_price,book_author) values 11 ('論語',25.6,'孔子'), 12 ('平凡的世界',35.8,'路遙'); 13
-
建立無參儲存過程
1 --1.建立無參儲存過程 2 if (exists (select * from sys.objects where name = 'getAllBooks')) 3 drop proc proc_get_student 4 go 5 create procedure getAllBooks 6 as 7 select * from books; 8 --呼叫,執行儲存過程 9 exec getAllBooks;
-
修改儲存過程
1 alter procedure dbo.getAllBooks 2 as 3 select book_author from books;
-
刪除儲存過程
drop procedure getAllBooks;
-
重新命名儲存過程
sp_rename getAllBooks,proc_get_allBooks;
-
建立帶引數的儲存過程
儲存過程的引數分為兩種:輸入引數和輸出引數
輸入引數:用於向儲存過程傳入值,類似java語言或則c中的值傳遞。
輸出引數:用於呼叫儲存過程後,參會結果,類似java語言的按引用傳遞。
值傳遞和引用傳遞區別:
- 基本資料型別賦值屬於值傳遞;引用型別之間賦值屬於引用傳遞。
- 值傳遞傳遞的是實實在在的變數值;引用傳遞傳遞的是物件的引用地址。
- 值傳遞後,兩個變數改變的是各自的值;引用傳遞後,兩個引用改變的是同一個物件的狀態
(a)帶一個引數儲存過程
1 if (exists (select * from sys.objects where name = 'searchBooks')) 2 drop proc searchBooks 3 go 4 create proc searchBooks(@bookID int) 5 as 6 --要求book_id列與輸入引數相等 7 select * from books where book_id=@bookID; 8 --執行searchBooks 9 exec searchBooks 1;
(b)帶2個引數儲存過程
1 if (exists (select * from sys.objects where name = 'searchBooks1')) 2 drop proc searchBooks1 3 go 4 create proc searchBooks1( 5 @bookID int, 6 @bookAuth varchar(20) 7 ) 8 as 9 --要求book_id和book_Auth列與輸入引數相等 10 select * from books where [email protected] and book_auth=@bookAuth; 11 exec searchBooks1 1,'金庸';
(c)建立有返回值的儲存過程
1 if (exists (select * from sys.objects where name = 'getBookId')) 2 drop proc getBookId 3 go 4 create proc getBookId( 5 @bookAuth varchar(20),--輸入引數,無預設值 6 @bookId int output --輸入/輸出引數 無預設值 7 ) 8 as 9 select @bookId=book_id from books where book_auth=@bookAuth 10 --執行getBookId這個帶返回值的儲存過程 11 declare @id int --宣告一個變數用來接收執行儲存過程後的返回值 12 exec getBookId '孔子',@id output 13 select @id as bookId;--as是給返回的列值起一個名字
(d)建立帶萬用字元的儲存過程
1 if (exists (select * from sys.objects where name = 'charBooks')) 2 drop proc charBooks 3 go 4 create proc charBooks( 5 @bookAuthor varchar(20)='金%', 6 @bookName varchar(20)='%' 7 ) 8 as 9 select * from books where book_author like @bookAuth and book_name like @bookName; 10 --執行儲存過程charBooks 11 exec charBooks '孔%','論%';
(e)建立分頁儲存過程
1 if (object_id('book_page', 'P') is not null) 2 drop proc book_page 3 go 4 create proc book_page( 5 @TableName varchar(50), --表名 6 @ReFieldsStr varchar(200) = '*', --欄位名(全部欄位為*) 7 @OrderString varchar(200), --排序欄位(必須!支援多欄位不用加order by) 8 @WhereString varchar(500) =N'', --條件語句(不用加where) 9 @PageSize int, --每頁多少條記錄 10 @PageIndex int = 1 , --指定當前為第幾頁 11 @TotalRecord int output --返回總記錄數 12 ) 13 as 14 begin 15 --處理開始點和結束點 16 Declare @StartRecord int; 17 Declare @EndRecord int; 18 Declare @TotalCountSql nvarchar(500); 19 Declare @SqlString nvarchar(2000); 20 set @StartRecord = (@PageIndex-1)*@PageSize + 1 21 set @EndRecord = @StartRecord + @PageSize - 1 22 SET @TotalCountSql= N'select @TotalRecord = count(*) from ' + @TableName;--總記錄數語句 23 SET @SqlString = N'(select row_number() over (order by '+ @OrderString +') as rowId,'[email protected]+' from '+ @TableName;--查詢語句 24 -- 25 IF (@WhereString! = '' or @WhereString!=null) 26 BEGIN 27 SET @[email protected] + ' where '+ @WhereString; 28 SET @SqlString [email protected]+ ' where '+ @WhereString; 29 END 30 --第一次執行得到 31 --IF(@TotalRecord is null) 32 -- BEGIN 33 EXEC sp_executesql @totalCountSql,N'@TotalRecord int out',@TotalRecord output;--返回總記錄數 34 -- END 35 ----執行主語句 36 set @SqlString ='select * from ' + @SqlString + ') as t where rowId between ' + ltrim(str(@StartRecord)) + ' and ' + ltrim(str(@EndRecord)); 37 Exec(@SqlString) 38 END 39 --呼叫分頁儲存過程book_page 40 exec book_page 'books','*','book_id','',3,1,0; 41 42 -- 43 declare @totalCount int 44 exec book_page 'books','*','book_id','',3,1,@totalCount output; 45 select @totalCount as totalCount;--總記錄數。