存儲過程+遊標+事務

一丶 存儲過程

什麼是存儲過程:存儲過程可以說是一個記錄集吧,它是由一些T-SQL語句組成的代碼塊,這些T-SQL語句代碼像一個方法一樣實現一些功能(對單表或多表的增刪改查),然後再給這個代碼塊取一個名字,在用到這個功能的時候調用他就行了

存儲過程的好處

1.由於數據庫執行動作時,是先編譯後執行的。然而存儲過程是一個編譯過的代碼塊,所以執行效率要比T-SQL語句高。
2.一個存儲過程在程序在網絡中交互時可以替代大堆的T-SQL語句,所以也能降低網絡的通信量,提高通信速率。
3.通過存儲過程能夠使沒有權限的用戶在控制之下間接地存取數據庫,從而確保數據的安全。


存儲過程的一些基本語法:

1. 只返回單一記錄集的存儲過程 

-------------創建名爲GetUserAccount的存儲過程----------------
create Procedure GetUserAccount
as
select * from UserAccount
go


-------------執行上面的存儲過程----------------
exec GetUserAccount

2.沒有輸入輸出的存儲過程 

-------------創建名爲GetUserAccount的存儲過程----------------


create Procedure inUserAccount
as
insert into UserAccount (UserName,[PassWord],RegisterTime,RegisterIP) values(9,9,'2013-01-02',9)
go


-------------執行上面的存儲過程----------------


exec inUserAccount

3.有返回值的存儲過程 

-------------創建名爲GetUserAccount的存儲過程----------------


create Procedure inUserAccountRe
as
insert into UserAccount (UserName,[PassWord],RegisterTime,RegisterIP) values(10,10,'2013-01-02',10)
return @@rowcount
go


-------------執行上面的存儲過程----------------


exec inUserAccountRe

4.有輸入參數和輸出參數的存儲過程 

-------------創建名爲GetUserAccount的存儲過程----------------

create Procedure GetUserAccountRe
@UserName nchar(20),
@UserID int output
as
if(@UserName>5)
select @UserID=COUNT(*) from UserAccount where UserID>25
else
set @UserID=1000
go

-------------執行上面的存儲過程----------------

exec GetUserAccountRe '7',null

5. 同時具有返回值、輸入參數、輸出參數的存儲過程 

-------------創建名爲GetUserAccount的存儲過程----------------

create Procedure GetUserAccountRe1
@UserName nchar(20),
@UserID int output
as
if(@UserName>5)
select @UserID=COUNT(*) from UserAccount where UserID>25
else
set @UserID=1000
return @@rowcount
go

-------------執行上面的存儲過程----------------

exec GetUserAccountRe1 '7',null

6.同時返回參數和記錄集的存儲過程 

-------------創建名爲GetUserAccount的存儲過程----------------

create Procedure GetUserAccountRe2
@UserName nchar(20),
@UserID int output
as
if(@UserName>5)
select @UserID=COUNT(*) from UserAccount where UserID>25
else
set @UserID=1000
select * from UserAccount
return @@rowcount
go

-------------執行上面的存儲過程----------------

exec GetUserAccountRe2 '7',null

7.返回多個記錄集的存儲過程 

-------------創建名爲GetUserAccount的存儲過程----------------

create Procedure GetUserAccountRe3
as
select * from UserAccount
select * from UserAccount where UserID>5
go

-------------執行上面的存儲過程----------------

exec GetUserAccountRe3



二丶 遊標

在關係數據庫中,我們對於查詢的思考是面向集合的。

 而遊標則是面向行的。

 


遊標的寫法:

declare test_course(定義的變量名) cursor for select *from 表名


打開遊標

open test_course

循環讀取遊標: 

next:

declare test_course cursor  for  select *from [dbo].[Info_User] open test_course 

fetch next from test_course   while @@fetch_status=0 begin fetch next from test_course  end

(FIRST),最後一行(LAST),下一行(NEXT),上一行(PRIOR),直接跳到某行(ABSOLUTE(n)),相對於目前跳幾行(RELATIVE(n)):

對於使用這些參數來讀取數據必須指定scroll選項:

declare test_two cursor scroll for  select *from [dbo].[Info_User]
open test_two
fetch LAST  from test_two 

使用 FETCH 將值存入變量

 fetch next from mycursor into @ID,@ExpertID,@UserID      

三丶 事務

事務:保持邏輯數據一致性與可恢復性,必不可少的利器。

書面解釋:事務具有原子性,一致性,隔離性,持久性。

  • 原子性:事務必須是一個自動工作的單元,要麼全部執行,要麼全部不執行。
  • 一致性:事務結束的時候,所有的內部數據都是正確的。
  • 隔離性:併發多個事務時,各個事務不干涉內部數據,處理的都是另外一個事務處理之前或之後的數據。
  • 持久性:事務提交之後,數據是永久性的,不可再回滾

 create procedure mon --創建存儲過程,定義幾個變量

@toID int,    --接收轉賬的賬戶

@fromID int ,  --轉出自己的賬戶

@momeys money --轉賬的金額

as

begin tran --開始執行事務

 

update bb set moneys=moneys-@momeys where ID=@fromID -執行的第一個操作,轉賬出錢,減去轉出的金額

update bb set moneys=moneys+@momeys where ID=@toID --執行第二個操作,接受轉賬的金額,增加

 

if @@error<>0 --判斷如果兩條語句有任何一條出現錯誤

begin rollback tran –開始執行事務的回滾,恢復的轉賬開始之前狀態

return 0

end

go

 

else   --如何兩條都執行成功

begin commit tran 執行這個事務的操作

return 1

end

go     





存儲過程+遊標+事務

複製代碼

ALTER procedure [dbo].[ExpertOrderBack]

AS
--聲明幾個變量 
declare @UserID int-- 提問的用戶ID
declare @ExpertUserID int --回答問題的專家ID
declare @ExpertID int    
declare @Baodan decimal  --報單賬戶
declare @Price decimal --諮詢一次的價格
declare @errors int
declare @ID int
 


declare mycursor cursor for select ID,ExpertID,UserID from ExpertOrder where OrderState=0 and OdertTime<dateadd(day,-7,getdate())
 --打開遊標  
    open mycursor      
    --從遊標裏取出數據賦值到我們剛纔聲明的3個變量中  
    fetch next from mycursor into @ID,@ExpertID,@UserID      
    --判斷遊標的狀態  
    -- 0 fetch語句成功      
    ---1 fetch語句失敗或此行不在結果集中      
    ---2 被提取的行不存在  
    while (@@fetch_status=0)  
    begin    
--通過ExpertID 獲取專家對應的用戶ID
Select @ExpertUserID=(select UserId from Expert where ID=@ExpertID)
Select @Price=(select Price from Expert where ID=@ExpertID)
Select @Baodan=(select BaodanGold from Info_User where UserID=@ExpertUserID)


  begin  tran --開始執行事務


  --判斷用戶的金額是否足夠
if @Baodan<@Price
begin
set @errors=@@ERROR+1
end


--開始進行業務上變動
update ExpertOrder set OrderState=3,IsSatisfaction=1,IsAudit=1 where ID=@ID
insert Info_Transaction(UserID,TranUserAccountType,TranType,BeforeTranMoney,TranMeney,EndTranMoney,Notes,IsCancel,TranCurrency,AddTime,IsDelete) values(@ExpertUserID,0,9,@Baodan,@Price,@Baodan+@Price,'會員未確認,系統自動扣款',0,'人民幣',GETDATE(),0)
update Info_User set BaodanGold=@Baodan+@Price where UserID=@ExpertUserID
 
if @errors<>0 --判斷  如果兩條語句有任何一條出現錯誤。(如果前面的SQL 語句執行沒有錯誤,則返回0)
begin
print '出現錯誤'
rollback tran --開始執行事務的回滾,恢復轉賬開始之前的狀態
return 0
end
 
else  --如果兩個語句都執行成功
begin
commit tran --執行這個事務的操作
end





    
       print '遊標成功取出一條數據'  
       print @ExpertID  
       print @UserID   
   print @ID
  
  
       fetch next from mycursor into @ID,@ExpertID,@UserID  
    end  
    --關閉遊標  
    close mycursor  
    --撤銷遊標  
    DEALLOCATE mycursor   

複製代碼


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章