日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

SQL 存储过程入门(事务)

發布時間:2024/9/20 数据库 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SQL 存储过程入门(事务) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本篇我們來講一下事務處理技術。

為什么要使用事務呢,事務有什么用呢,舉個例子。

假設我們現在有個業務,當做成功某件事情的時候要向2張表中插入數據,A表,B表,我們插入的順序是先插入A,再插入B表,如果都順利插入成功了,當然沒有問題,如果任意一張表插入失敗了,而另一張表插入成功了,插入成功的表就是垃圾數據了。我們要判斷,任意一張表插入失敗都回滾,就是都不插入,這就是事務的基本使用。

一,sql事務定義

所謂事務是用戶定義的一個數據庫操作序列,是一個不可分割的工作單位。他包含的所有數據庫操作命令作為一個整體一起向系提交或撤消 ,這些操作要么全做,要么全不做,

?例如在關系數據庫中,一個事務可以是一條sql語句,或者是一組sql語句或者是整個程序。

二,sql事務語句

開始事務:BEGIN TRANSACTION
提交事務:COMMIT TRANSACTION
回滾事務:ROLLBACK TRANSACTION

事務通常是以begin transaction開始的,以commit或rollback 結束,commit表示提交,既提交事務的所有操作。具體的說就是將事務中所有對數據庫的更新寫到磁盤

上的物理數據中去,事務正常結束。

Rollback表示回滾,在事務運行的過程中發生了某種故障,事務不能繼續執行,系統將事務中對數據庫的所有已完成的操作全部取消,回滾到事務開始時的狀態。這里的操作

指對數據庫的更新操作。

三,事務的特性(ACID Propertites)

原子性(Atomicity):事務是數據庫的邏輯工作單位,事務中包括的諸操作要么都做,要么都不做。

一致性(Consistency):事物完成時,數據必須是一致的,也就是說,和事物開始之前,數據存儲中的數據處于一致狀態。保證數據的無損

隔離性(Isolation):一個事務的執行不能被其他事務干擾。并發執行的各個事務之間不能互相干擾。

持續性(Durability):指一個事務一旦提交,它對數據庫中數據的改變時永久性的。

四,存儲過程使用事務

這里做好準備工作,建立一張表,插入一條數據。

--新建表 create table userinfo (ID int identity(1,1) ,UserName varchar(20) primary key,UserPwd varchar(20) ,RegisterTime datetime ) --初始化插入一條記錄 insert into userinfo(username,userpwd,RegisterTime) values('admin','admin',getdate())select * from userinfo

-------------------

ID userName UserPwd RegisterTime

1 admin admin 2013-04-13 10:30:36.387

?從表結構看出,UserName是主鍵,是唯一值,現在要插入兩條數據

Create Procedure MyProcedureASBeginSet NOCOUNT ON; Set XACT_ABORT on; --這句話非常重要Begin Tran --開始事務insert into userinfo(username,userpwd,RegisterTime) values('admin','admin',getdate())insert into userinfo(username,userpwd,RegisterTime) values('jack','jack',getdate())Commit Tran --提交事務End

執行

exec MyProcedure/* 消息 2627,級別 14,狀態 1,過程 MyProcedure,第 9 行 違反了 PRIMARY KEY 約束 'PK__userinfo__C9F284577F60ED59'。不能在對象 'dbo.userinfo' 中插入重復鍵。*/ --查看數據庫------------------------------------------------ 12 admin admin 2013-04-13 10:41:22.457 上面說了 Set XACT_ABORT on; 這句話非常重要 ,為什么呢?我們來設置為off的時候來看效果
Create Procedure MyProcedureASBeginSet NOCOUNT ON; Set XACT_ABORT off; --這句話非常重要Begin Tran --開始事務insert into userinfo(username,userpwd,RegisterTime) values('admin','admin',getdate())insert into userinfo(username,userpwd,RegisterTime) values('jack','jack',getdate())Commit Tran --提交事務End

執行并查看結果

exec MyProcedure/* 消息 2627,級別 14,狀態 1,過程 MyProcedure,第 9 行 違反了 PRIMARY KEY 約束 'PK__userinfo__C9F284577F60ED59'。不能在對象 'dbo.userinfo' 中插入重復鍵。 語句已終止。*/--查看結果 select * from userinfo
------------------------------------------- 12 admin admin 2013-04-13 10:41:22.457 15 jack jack 2013-04-13 10:44:05.203

這里我們將XACT_ABORT 設置為off,事務中執行已經出現錯誤了,但是還是將 “jack”這條記錄插入進去了。這就違反了事務的一致性原則了。所以我們要將XACT_ABORT 設置為ON的原因。

看看下面說明:

1?、使用存儲過程執行事物,需要開啟XACT_ABORT參數(默認值為Off),將該參數設置為On,表示當執行事務時,如果出錯,會將transcation設置為uncommittable狀態,那么在語句塊批處理結束后將回滾所有操作;如果該參數設置為Off,表示當執行事務時,如果出錯,出錯的語句將不會執行,其他正確的操作繼續執行。

2、當SET NOCOUNT 為 ON 時,不返回計數(計數表示受 Transact-SQL 語句影響的行數,例如在Sql server查詢分析器中執行一個delete操作后,下方窗口會提示(3)Rows Affected)。當?? SET NOCOUNT 為 OFF 時,返回計數,我們應該在存儲過程的頭部加上SET NOCOUNT ON 這樣的話,在退出存儲過程的時候加上 SET NOCOUNT OFF這樣的話,以達到優化存儲過程的目的。

五,存儲過程中事務和try…catch聯合使用

如果我們在存儲過程事務中出現了錯誤,我們不想顯示錯誤,我們想動態處理這些錯誤信息,比如出錯了,我們回滾,我們設置某個屬性的值,這里就會用到try ,catch了
還是從例子出發

Create Procedure MyProcedureASBeginSet NOCOUNT ON; Set XACT_ABORT ON; --這句話非常重要begin tryBegin Tran --開始事務insert into userinfo(username,userpwd,RegisterTime) values('admin','admin',getdate())insert into userinfo(username,userpwd,RegisterTime) values('jack','jack',getdate())Commit Tran --提交事務end trybegin catch--在此可以使用xact_state()來判斷是否有不可提交的事務,不可提交的事務--表示在事務內部發生錯誤了。Xact_state()有三種值:-1.事務不可提交;--1.事務可提交;0.表示沒有事務,此時commit或者rollback會報錯。if xact_state()=-1rollback tran;end catch Set XACT_ABORT OFF; End

當我們執行的時候不會再出現剛才的那種錯誤了,

exec MyProcedure-------------- 命令已成功完成。 --沒有出現那種錯誤select * from userinfo -------------------------------------------------- 22 admin admin 2013-04-13 10:55:50.653

可以看到,事務回滾了,沒有插入數據了。

如果我們想看到錯誤信息呢,再來看個例子 Create Procedure MyProcedureASBeginSet NOCOUNT ON; Set XACT_ABORT ON; --這句話非常重要begin tryBegin Tran --開始事務insert into userinfo(username,userpwd,RegisterTime) values('admin','admin',getdate())insert into userinfo(username,userpwd,RegisterTime) values('jack','jack',getdate())Commit Tran --提交事務end trybegin catch--在此可以使用xact_state()來判斷是否有不可提交的事務,不可提交的事務--表示在事務內部發生錯誤了。Xact_state()有三種值:-1.事務不可提交;--1.事務可提交;0.表示沒有事務,此時commit或者rollback會報錯。if xact_state()=-1beginrollback tran;SELECT ERROR_NUMBER() AS ErrorNumber,ERROR_MESSAGE() AS ErrorMessage;endend catch End

執行

exec MyProcedure-------------------------------- ErrorNumber ErrorMessage 2627 違反了 PRIMARY KEY 約束 'PK__userinfo__C9F284577F60ED59'。不能在對象 'dbo.userinfo' 中插入重復鍵。

說明:1、捕獲錯誤的函數有很多,如下:

???????? ? ERROR_NUMBER() 返回錯誤號。

    ERROR_SEVERITY() 返回嚴重性。

    ERROR_STATE() 返回錯誤狀態號。

    ERROR_PROCEDURE() 返回出現錯誤的存儲過程或觸發器的名稱。

    ERROR_LINE() 返回導致錯誤的例程中的行號。

    ERROR_MESSAGE() 返回錯誤消息的完整文本。該文本可包括任何可替換參數所提供的值,如長度、對象名或時間。



在存儲過程中使用事務時,如果存在try…catch語句塊,那么當捕獲到錯誤時,需要在catch語句塊中手動進行Rollback操作,否則系統會給客戶端傳遞一條錯誤信息。如果在存儲過程開始處將set xact_abort on,那么當有錯誤發生時,系統會將當前事務置為不可提交狀態,即會將xact_state()置為-1,此時只可以對事務進行Rollback操作,不可進行提交(commit)操作,那么我們在catch語句塊中就可以根據xact_state()的值來判斷是否有事務處于不可提交狀態,如果有則可以進行rollback操作了。

如果在存儲過程開始處將set xact_abort off,那么當有錯誤發生時,系統不會講xact_state()置為-1,那么我們在catch塊中就不可以根據該函數值來判斷是否需要進行rollback了,但是我們可以根據@@Trancount全局變量來判斷,如果在catch塊中判斷出@@Trancount數值大于0,代表還有未提交的事務,既然進入catch語句塊了,那么還存在未提交的事務,該事務應該是需要rollback的,但是這種方法在某些情況下可能判斷的不準確。

推薦的方法還是將set xact_abort on,然后在catch中判斷xact_state()的值來判斷是否需要Rollback操作。

下面再來看個例子,在實踐中不斷熟悉。

這個例子就是,如果插入重復的數據給出提示信息并返回

-- 判斷要創建的存儲過程名是否存在 if Exists(Select name From sysobjects Where name = 'P_InsertUser' And type = 'P') -- 刪除存儲過程 Drop Procedure dbo.P_InsertUser Go USE [StoreTest] GOcreate Procedure [dbo].[P_InsertUser] @UserName varchar(100), @UserPwd varchar(100) AS Begin Set NOCOUNT ON; Set XACT_ABORT ON; --這句話非常重要Begin tryif(isnull(@UserName,'')='')
   beginprint 'UserName is empty';
     return;
enddeclare @iCount int;set @iCount = 0;select @iCount = Count(1) from userinfo with(nolock) where username=@UserName;if( @iCount > 0 )beginprint 'the current name already exist';returnendBegin Tran --開始事務,事務中不能有return語句--insertinsert into userinfo(username,userpwd,RegisterTime )values(@UserName,@UserPwd,getdate())Commit Tran --提交事務 end try begin catch --在此可以使用xact_state()來判斷是否有不可提交的事務,不可提交的事務 --表示在事務內部發生錯誤了。Xact_state()有三種值:-1.事務不可提交; --1.事務可提交;0.表示沒有事務,此時commit或者rollback會報錯。 if xact_state()=-1 beginrollback tran; --事務回滾SELECT ERROR_NUMBER() AS ErrorNumber,ERROR_MESSAGE() AS ErrorMessage; end end catch Set XACT_ABORT off; End--調用存儲過程 exec [P_InsertUser] '','admin'select * from userinfoGO ? 事務的東西很多,這里希望能起到拋磚引玉的效果。

總結

以上是生活随笔為你收集整理的SQL 存储过程入门(事务)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。