1. 程式人生 > >Sql語法高級應用之三:存儲過程

Sql語法高級應用之三:存儲過程

while 重新 begin dealloc scom 查詢信息 普通 not null lar

一、存儲過程概述

  SQL Server中的存儲過程是使用T_SQL編寫的代碼段。它的目的在於能夠方便的從系統表中查詢信息,或者完成與更新數據庫表相關的管理任務和其他的系統管理任務.T_SQL語句是SQL Server數據庫與應用程序之間的編程接口。在很多情況下,一些代碼會被開發者重復編寫多次,如果每次都編寫相同功能的代碼,不但繁瑣,而且容易出錯,而且由於SQL Server逐條的執行語句會降低系統的運行效率。

  簡而言之,存儲過程就是SQL Server為了實現特定任務,而將一些需要多次調用的固定操作語句,或者某些業務過於繁瑣,需要編寫大量邏輯和查詢,嚴重影響程序性能,編寫成程序段,這些程序段存儲在服務器上,有數據庫服務器通過程序來調用。

二、存儲過程的優點

  1. 存儲過程加快系統運行速度,存儲過程只在創建時編譯,以後每次執行時不需要重新編譯。
  2. 存儲過程可以封裝復雜的數據庫操作,簡化操作流程,例如對多個表的更新,刪除等。
  3. 可實現模塊化的程序設計,存儲過程可以多次調用,提供統一的數據庫訪問接口,改進應用程序的可維護性。
  4. 存儲過程可以增加代碼的安全性,對於用戶不能直接操作存儲過程中引用的對象,SQL Server可以設定用戶對指定存儲過程的執行權限。
  5. 存儲過程可以降低網絡流量,存儲過程代碼直接存儲於數據庫中,在客戶端與服務器的通信過程中,不會產生大量的T_SQL代碼流量。

三、存儲過程分類

1.系統存儲過程

??系統存儲過程是 SQL Server系統自身提供的存儲過程,可以作為命令執行各種操作。

??系統存儲過程主要用來從系統表中獲取信息,使用系統存儲過程完成數據庫服務器的管理工作,為系統管理員提供幫助,為用戶查看數據庫對象提供方便,系統存儲過程位於數據庫服務器中,並且以sp_開頭,系統存儲過程定義在系統定義和用戶定義的數據庫中,在調用時不必在存儲過程前加數據庫限定名。例如:sp_rename系統存儲過程可以修改當前數據庫中用戶創建對象的名稱,sp_helptext存儲過程可以顯示規則,默認值或視圖的文本信息,SQL SERVER服務器中許多的管理工作都是通過執行系統存儲過程來完成的,許多系統信息也可以通過執行系統存儲過程來獲得。

??系統存儲過程創建並存放在與系統數據庫master中,一些系統存儲過程只能由系統管理員使用,而有些系統存儲過程通過授權可以被其它用戶所使用。

2.用戶存儲過程(自定義存儲過程)

??自定義存儲過程即用戶使用T_SQL語句編寫的、為了實現某一特定業務需求,在用戶數據庫中編寫的T_SQL語句集合,自定義存儲過程可以接受輸入參數、向客戶端返回結果和信息,返回輸出參數等。創建自定義存儲過程時,存儲過程名前加上"##"表示創建了一個全局的臨時存儲過程;存儲過程前面加上"#"時,表示創建的局部臨時存儲過程。局部臨時存儲過程只能在創建它的回話中使用,會話結束時,將被刪除。這兩種存儲過程都存儲在tempdb數據庫中。

用戶定義的存儲過程分為兩類:T_SQL 和CLR

T_SQL:存儲過程是值保存的T_SQL語句集合,可以接受和返回用戶提供的參數,存儲過程也可能從數據庫向客戶端應用程序返回數據。

CLR存儲過程是指引用Microsoft.NET Framework公共語言的方法存儲過程,可以接受和返回用戶提供的參數,它們在.NET Framework程序集是作為類的公共靜態方法實現的。

3.擴展存儲過程

?擴展存儲過程是以在SQL SERVER環境外執行的動態連接(DLL文件)來實現的,可以加載到SQL SERVER實例運行的地址空間中執行,擴展存儲過程可以用SQL SERVER擴展存儲過程API編程,擴展存儲過程以前綴"xp_"來標識,對於用戶來說,擴展存儲過程和普通話存儲過程一樣,可以用相同的方法來執行。

四、存儲過程實際引用

1. 創建無參存儲過程

--1.創建無參存儲過程
if (exists (select * from sys.objects where name = ‘getAllBooks‘))
    drop proc proc_get_student
go
create procedure getAllBooks
as
select * from books;
--調用,執行存儲過程
exec getAllBooks;

2. 修改存儲過程

alter procedure dbo.getAllBooks 
as
select book_auth from books;

3. 刪除存儲過程

drop procedure getAllBooks;

4. 重命名存儲過程

sp_rename getAllBooks,proc_get_allBooks;

5. 創建帶參數的存儲過程,這也是存儲過程最常見的形式

存儲過程的參數分為兩種:輸入參數和輸出參數

輸入參數:用於向存儲過程傳入值,類似java語言或則c中的值傳遞。

輸出參數:用於調用存儲過程後,參會結果,類似java語言的按引用傳遞。

值傳遞和引用傳遞區別:

  • 基本數據類型賦值屬於值傳遞;引用類型之間賦值屬於引用傳遞。
  • 值傳遞傳遞的是實實在在的變量值;引用傳遞傳遞的是對象的引用地址。
  • 值傳遞後,兩個變量改變的是各自的值;引用傳遞後,兩個引用改變的是同一個對象的狀態

5.1)帶一個參數存儲過程

if (exists (select * from sys.objects where name = ‘searchBooks‘))
    drop proc searchBooks
go
create proc searchBooks(@bookID int)
as
    --要求book_id列與輸入參數相等
    select * from books where book_id=@bookID;
--執行searchBooks
exec searchBooks 1;

5.2)帶2個參數存儲過程

if (exists (select * from sys.objects where name = ‘searchBooks1‘))
    drop proc searchBooks1
go
create proc searchBooks1(
    @bookID int,
    @bookAuth varchar(20)
)
as
    --要求book_id和book_Auth列與輸入參數相等
    select * from books where book_id=@bookID and book_auth=@bookAuth;
exec searchBooks1 1,‘金庸‘;

5.3)創建有返回值的存儲過程

if (exists (select * from sys.objects where name = ‘getBookId‘))
    drop proc getBookId
go
create proc getBookId(
    @bookAuth varchar(20),--輸入參數,無默認值
    @bookId int output --輸入/輸出參數 無默認值
)
as
    select @bookId=book_id from books where book_auth=@bookAuth
--執行getBookId這個帶返回值的存儲過程
declare @id int --聲明一個變量用來接收執行存儲過程後的返回值
exec getBookId ‘孔子‘,@id output
select @id as bookId;--as是給返回的列值起一個名字

5.4)創建帶通配符的存儲過程

if (exists (select * from sys.objects where name = ‘charBooks‘))
    drop proc charBooks
go
create proc charBooks(
    @bookAuth varchar(20)=‘金%‘,
    @bookName varchar(20)=‘%‘
)
as 
    select * from books where book_auth like @bookAuth and book_name like @bookName;
--執行存儲過程charBooks
exec  charBooks    ‘孔%‘,‘論%‘;

5.5)加密存儲過程

with encryption子句對用戶隱藏存儲過程的文本.下例創建加密過程,使用 sp_helptext 系統存儲過程獲取關於加密過程的信息,然後嘗試直接從 syscomments 表中獲取關於該過程的信息。

if (object_id(‘books_encryption‘, ‘P‘) is not null)
    drop proc books_encryption
go
create proc books_encryption 
with encryption
as 
    select * from books;
--執行此過程books_encryption
exec books_encryption;
exec sp_helptext ‘books_encryption‘;--控制臺會顯示"對象 ‘books_encryption‘ 的文本已加密。"

5.6)不緩存存儲過程

--with  recompile不緩存
if (object_id(‘book_temp‘, ‘P‘) is not null)
    drop proc book_temp
go
create proc book_temp
with recompile
as
    select * from books;
go

exec book_temp;
exec sp_helptext ‘book_temp‘;

5.7)創建帶遊標參數的存儲過程

if (object_id(‘book_cursor‘, ‘P‘) is not null)
    drop proc book_cursor
go
create proc book_cursor
    @bookCursor cursor varying output
as
    set @bookCursor=cursor forward_only static for
    select book_id,book_name,book_auth from books
    open @bookCursor;
go
--調用book_cursor存儲過程
declare @cur cursor,
        @bookID int,
        @bookName varchar(20),
        @bookAuth varchar(20);
exec book_cursor @bookCursor=@cur output;
fetch next from @cur into @bookID,@bookName,@bookAuth;
while(@@FETCH_STATUS=0)
begin 
    fetch next from @cur into @bookID,@bookName,@bookAuth;
    print ‘bookID:‘+convert(varchar,@bookID)+‘ , bookName: ‘+ @bookName
            +‘ ,bookAuth: ‘+@bookAuth;
end
close @cur    --關閉遊標
DEALLOCATE @cur; --釋放遊標

5.8)創建分頁存儲過程

if (object_id(‘book_page‘, ‘P‘) is not null)
    drop proc book_page
go
create proc book_page(
    @TableName varchar(50),            --表名
    @ReFieldsStr varchar(200) = ‘*‘,   --字段名(全部字段為*)
    @OrderString varchar(200),         --排序字段(必須!支持多字段不用加order by)
    @WhereString varchar(500) =N‘‘,  --條件語句(不用加where)
    @PageSize int,                     --每頁多少條記錄
    @PageIndex int = 1 ,               --指定當前為第幾頁
    @TotalRecord int output            --返回總記錄數
)
as
begin
     --處理開始點和結束點
    Declare @StartRecord int;
    Declare @EndRecord int; 
    Declare @TotalCountSql nvarchar(500); 
    Declare @SqlString nvarchar(2000);    
    set @StartRecord = (@PageIndex-1)*@PageSize + 1
    set @EndRecord = @StartRecord + @PageSize - 1 
    SET @TotalCountSql= N‘select @TotalRecord = count(*) from ‘ + @TableName;--總記錄數語句
    SET @SqlString = N‘(select row_number() over (order by ‘+ @OrderString +‘) as rowId,‘+@ReFieldsStr+‘ from ‘+ @TableName;--查詢語句
    --
    IF (@WhereString! = ‘‘ or @WhereString!=null)
        BEGIN
            SET @TotalCountSql=@TotalCountSql + ‘  where ‘+ @WhereString;
            SET @SqlString =@SqlString+ ‘  where ‘+ @WhereString;            
        END
    --第一次執行得到
    --IF(@TotalRecord is null)
    --   BEGIN
           EXEC sp_executesql @totalCountSql,N‘@TotalRecord int out‘,@TotalRecord output;--返回總記錄數
    --  END
    ----執行主語句
    set @SqlString =‘select * from ‘ + @SqlString + ‘) as t where rowId between ‘ + ltrim(str(@StartRecord)) + ‘ and ‘ +  ltrim(str(@EndRecord));
    Exec(@SqlString)    
END
--調用分頁存儲過程book_page
exec book_page ‘books‘,‘*‘,‘book_id‘,‘‘,3,1,0;

--
declare @totalCount int
exec book_page ‘books‘,‘*‘,‘book_id‘,‘‘,3,1,@totalCount output; 
select @totalCount as totalCount;--總記錄數。

PS:歡迎掃描下方二維碼或點擊鏈接,加入QQ群

技術分享圖片

技術分享圖片

Sql語法高級應用之三:存儲過程