20180928 SQL SERVER 事務回滾


  • begin tran:設置起點
  • commit tran:使事務成為數據庫中永久的、不可逆轉的一部分
  • rollback tran:本質上說想要忘記它曾經發生過
  • save tran:創建一個特定標記,只允許部分回滾

begin tran

事務的開始可能是事物過程中最容易理解的概念。它唯一的目的就是表示一個單元的開始。如果由於某種原因,不能或者不想提交事務,那么這就是所有數據庫活動將要回滾的起點。也就是說,數據庫會忽略這個起點之后的最終沒有提交的所有語句。
語法如下:

begin tran[saction] [<transaction name>|<@transaction variable>][with mark[<'description'>]] 
  • 1

commit tran

事務的提交是一個事務的終點。當發出commit tran命令時,可以認為事務執行完畢。也就是說,事務所包含的所有Sql語句執行完畢,事務的影響現在是持久的並會繼續,即使系統發生故障也不受影響(只要有備份或數據庫文件沒有被物理破壞就行)。撤銷已完成事務的唯一方法就是發出一個新的事務,從功能上而言,該事務是對上一個事務的反轉。
commit tran語法如下:

commit tran[saction][<transaction name>|<@transaction variable>] 
  • 1

rollback tran

rollback是進行事務回滾,從關聯的begin語句開始發生的任何事情都會被忘記,即撤銷該事務包含的所有操作。除了允許保存點外,rollback的語法看上去和begin或commit語句一樣:

rollback tran[saction][<transaction name>|<save point name>|<@transaction variable>|<@savepoint variable>]
  • 1

save tran

保存事務從本質上說就是創建書簽(bookmark)。為書簽建立一個名稱,在建立了“書簽”之后,可以在回滾中引用它。創建書簽的好處是可以回滾到代碼中的特定點上-只要為想要回滾到的那個保存點命名。
語法如下:

save tran[saction][<save point name>|<@savepoint variable>] 

SQL事務回滾

指定當   Transact-SQL   語句產生運行時錯誤時,Microsoft&reg;   SQL   Server&#8482;   是否自動回滾當前事務

方案一:

 代碼如下 復制代碼
SET   XACT_ABORT   ON--如果產生錯誤自動回滾
GO
BEGIN   TRAN
INSERT   INTO   A   VALUES   (4)
INSERT   INTO   B   VALUES   (5)
COMMIT   TRAN

也可以使用_ConnectionPtr 對象的方法: BeginTrans、CommitTrans、RollbackTrans,使用該系列函數判斷並回滾。一旦調用了 BeginTrans 方法, 在調用 CommitTrans 或 RollbackTrans 結束事務之前, 數據庫將不再立即提交所作的任何更改。
方案二

 代碼如下 復制代碼
BEGIN TRANSACTION
INSERT INTO A   values  (4)   ----- 該表含有觸發器,UPDATE其他表
IF @@error <> 0  --發生錯誤
   BEGIN
     ROLLBACK TRANSACTION
         
   END
ELSE
   BEGIN
     COMMIT TRANSACTION
       
   END


sql事務結合asp.net兩種用法

在sql server+ .net 開發環境下,有兩種方法能夠完成事務的操作,保持數據庫的數據完整性;一個就是用sqlserver/42850.htm target=_blank >sql存儲過程,另一個就是在ADO.NET中一種簡單的事務處理;現在通過一個典型的銀行轉賬的例子來說明一下這兩個例子的用法我們先來看看sql存儲過程是如何來完成事務的操作的:首先創建一個表:

 代碼如下 復制代碼

create database aaaa --創建一個表,包含用戶的帳號和錢數gouse aaaacreate table bb( ID int not null primary key,  --帳號 moneys money    --轉賬金額)insert into bb values ('1','2000') --插入兩條數據insert into bb values ('2','3000')用這個表創建一個存儲過程:
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

 

接下來看看C#.net 是如何調用這個存儲過程的:

   

 代碼如下 復制代碼

protected void Button1_Click(object sender, EventArgs e)

    {

        SqlConnection con =new SqlConnection(@"Data Source=.SQLEXPRESS;database=aaaa;uid=sa;pwd=jcx"); //連接字符串

        SqlCommand cmd = new SqlCommand("mon",con); //調用存儲過程

        cmd.CommandType = CommandType.StoredProcedure;

        con.Open();

        SqlParameter prar = new SqlParameter();//傳遞參數

        cmd.Parameters.AddWithValue("@fromID", 1);

        cmd.Parameters.AddWithValue("@toID", 2);

        cmd.Parameters.AddWithValue("@momeys",Convert.ToInt32( TextBox1.Text) );

 

        cmd.Parameters.Add("@return", "").Direction = ParameterDirection.ReturnValue;//獲取存儲過程的返回值

        cmd.ExecuteNonQuery();

        string value = cmd.Parameters["@return"].Value.ToString();//把返回值賦值給value

        if (value == "1")

        {

            Label1.Text = "添加成功";

        }

        else

        {

            Label1.Text = "添加失敗";

       }

}

這個也就是在存儲過程里添加事務,再來看看不在數據庫寫sql存儲過程,ADO.NET是如何處理事務的:

 代碼如下 復制代碼

protected void Button2_Click(object sender, EventArgs e)

    {

        SqlConnection con = new SqlConnection(@"Data Source=.SQLEXPRESS;database=aaaa;uid=sa;pwd=jcx");

        con.Open();

        SqlTransaction tran = con.BeginTransaction();//先實例SqlTransaction類,使用這個事務使用的是con 這個連接,使用BeginTransaction這個方法來開始執行這個事務

        SqlCommand cmd = new SqlCommand();

        cmd.Connection = con;

        cmd.Transaction = tran;

        try

        {

             //在try{} 塊里執行sqlcommand命令,

            cmd.CommandText = "update bb set moneys=moneys-'" + Convert.ToInt32(TextBox1.Text) + "' where ID='1'";

            cmd.ExecuteNonQuery();

            cmd.CommandText = "update bb set moneys=moneys+' aa ' where ID='2'";

            cmd.ExecuteNonQuery();

            tran.Commit();//如果兩個sql命令都執行成功,則執行commit這個方法,執行這些操作

 

            Label1.Text = "添加成功";

        }

        catch

        {

            Label1.Text = "添加失敗";

            tran.Rollback();//如何執行不成功,發生異常,則執行rollback方法,回滾到事務操作開始之前;

        }

 

    }

這就是兩個事務不同用法的簡單例子,ADO.NET 事務處理的方法看起來比較簡單,但是他要使用同一個連接來執行這些操作,要是同時使用幾個數據庫來用一個事務執行,這樣就比較繁瑣,但是要是用sql存儲過程,這樣就相對比較簡單

set XACT_ABORT ON   ---如果不設置該項為ON,在sql中默認為OFF,那么只只回滾產生錯誤的 Transact-SQL 語句;設為ON,回滾整個事務

begin tran t1 ---啟動一個事務

update [water].[dbo].[ErrorInf]
set ErrorMessage='test'
where ID=6

insert into [water].[dbo].[ErrorInf]([ID],ErrorMessage,[Description])
Values(1,'test1','test1')

commit tran t1  ---提交事務
復制代碼
復制代碼

功能:實現begin tran 和commit tran之間的語句,任一如果出現錯誤,所有都不執

 

事務不是有錯就回滾的,在不寫rollback的情況下,並不是什么錯誤都會回滾事務,有時回滾當前語句,有時回滾整個事務

如例

begin tran 
insert into dbo.area values('1111')
insert into dbo.area values('2222')
select 1/0
insert into dbo.area values('333')
commit

 

像這樣,就算中間有錯,也不會回滾,結果會成功添加三條記錄

但有人說,比如重大錯誤,這事務也會所有回滾,只是我無法重現重大錯誤罷了

普通錯誤如果想回滾整個事務,只要加個set XACT_ABORT on就可以了

復制代碼
復制代碼
set XACT_ABORT on

begin tran

insert into dbo.area values('1111')
insert into dbo.area values('2222')
select 1/0
insert into dbo.area values('333')

commit
復制代碼
復制代碼

 

 

但也有人寫一堆@@error,如

復制代碼
復制代碼
begin tran 

insert into dbo.area values('1111')
if @@error>0
  rollback

insert into dbo.area values('2222')
if @@error>0
  rollback

select 1/0
if @@error>0
  rollback

insert into dbo.area values('333')
if @@error>0
  rollback

commit
復制代碼
復制代碼

 

當然也行,不過寫起來太麻煩了.

后來發現sql2005支持try

復制代碼
復制代碼
BEGIN TRY
   BEGIN TRANSACTION
     insert into dbo.area values('1111')
    insert into dbo.area values('2222')
    select 1/0
    insert into dbo.area values('333')
   COMMIT
END TRY
BEGIN CATCH
   IF @@TRANCOUNT > 0
     ROLLBACK

  DECLARE @ErrMsg nvarchar(4000), @ErrSeverity int
  SELECT @ErrMsg = ERROR_MESSAGE(),
         @ErrSeverity = ERROR_SEVERITY()

  RAISERROR(@ErrMsg, @ErrSeverity, 1)
END CATCH


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM