【997755.com澳门葡京】Server触发器及触发器中的事务,数据库事务回滚的用法

USE [TestDB]
GO
/****** 对象:  Table [dbo].[Person]    脚本日期: 11/23/2008 13:37:48 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Person](
    [PersonId] [nchar](18) NOT NULL,
    [PersonName] [nchar](20) NOT NULL,
 CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED 
(
    [PersonId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

 

事务管理是数量的要害特色。越发是对于部分支付系统,事务保险性对事情逻辑会有注重影响。golang的mysql驱动也卷入好了事情相关的操作。大家已经学习了db的Query和Exec方法管理查询和修改数据库。

引述

暗中认可情状下1旦进行一个事务中出现错误,则只回滚错误操作语句(正是说这句不实行了,算不上回滚),错误处以前或以往的准确性操作语句照旧会被交付。如:

动用的表结构如下:

tx对象

诚如查询利用的是db对象的秘技,事务则是应用此外三个目标。sql.Tx对象。使用db的Begin方法能够创立tx对象。tx对象也有数据库交互的Query,Exec和Prepare方法。用法和db的相干用法类似。查询或涂改的操作甘休之后,须要调用tx对象的Commit提交大概Rollback方法回滚。

若是创造了tx对象,事务管理都依赖与tx对象,这么些目的会从连接池中收取3个空余的总是,接下去的sql试行都基于这些三番五次,直到commit可能rollback调用之后,才会把连接释放到连接池。

在事务处理的时候,不能够采纳db的询问格局,即使后者能够获取数据,不过这不属于同2个事务管理,将不会承受commit和rollback的改变,2个简单易行的业务例子如下:

tx, err := db.Begin()tx.Exectx.Exectx.commit()

在tx中央银行使db是荒唐的:

tx, err := db.Begin()db.Exectx.Exectx.commit()

上述代码在调用db的Eexc方法的时候,tx会绑定连接到业务中,db则是额外的三个延续,两者不是同二个政工。必要注意,Begin和Commit方法,与sql语句中的BEGIN或COMMIT语句未有关联。


Use TestDB

Begin TransAction
    Insert Into Person(PersonId,PersonName)
                Values('1','Name1')
    Insert Into Person(PersonId,PersonName)
                Values('1','Name1')
    Insert Into Person(PersonId,PersonName)
                Values('3','Name3')
Commit TransAction
/*
    Select 一下 有'1','Name1'和'3','Name3',
    说明只有第二句的错误被取消了
*/

997755.com澳门葡京 1😉

事情与连接

始建Tx对象的时候,会从连接池中取出连接,然后调用相关的Exec方法的时候,连接仍旧会绑定在改事务管理中。在骨子里的事务管理中,go大概创设差别的三番五次,不过那多少个其余连接都不属于该专门的职业。例如地点例子中db创制的连日和tx的连日就不是二遍事。

业务的连年生命周期从Beigin函数调用起,直到Commit和Rollback函数的调用截至。事务也提供了prepare语句的利用形式,可是急需采用Tx.Stmt方法创造。prepare设计的初衷是数十次进行,对于事情,有一点都不小大概供给反复实践同3个sql。但是无论不奇怪的prepare和事务管理,prepare对于延续的田间管理都有点小复杂。因而私认为尽量防止在工作中使用prepare格局。举个例子上面例子就便于形成错误:

tx, _ := db.Begin()defer tx.Rollback()stmt, _ tx.Prepare("INSERT ...")defer stmt.Close()tx.Commit()

因为stmt.Close使用defer语句,即函数退出的时候再清理stmt,不过实在施行进程的时候,tx.Commit就已经出狱了两次三番。当函数退出的时候,再实施stmt.Close的时候,连接可能有被利用了。

     首先,
说下自个儿写篇小说的目标,俺盼望能把自家对触发器的驾驭,分享出来与你共同学习。固然您有对触发器和作业的概念,有个别掌握,那篇小说,对你的话会是异常的粗略,或能让您更进一步的摸底触发器里面包车型地铁有的逸事,和触发器台湾中华南理哲大学程集团作个传说。在那边小说里面,作者不会从触发器和作业的定义去描述,而是从周边的三种触发器类型(DML触发器
& DDL触发器)和After触发器 &  Instead Of
触发器的行使区别,起初聊到它们,然后是说与职业有关的传说。借使,你有怎么着建议和意见,都得以经过小说前边的复原与本身调换,或然通过E-Mail情势,与
小编沟通;小编的Email地址是:glal@163.com

全套回滚的措施一:打开 XACT_ABORT

USE [TestDB]
GO
/****** 对象:  Table [dbo].[Person]   
脚本日期: 15/103/二〇〇八 13:三7:4捌 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Person](
    [PersonId] [nchar](18) NOT NULL,
    [PersonName] [nchar](20) NOT NULL,
 CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED 
(
    [PersonId] ASC
)WITH (PAD_INDEX  = OFF,
STATISTICS_NORECOMPUTE  = OFF,
IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS  = ON,
ALLOW_PAGE_LOCKS  = ON)
ON [PRIMARY]
) ON [【997755.com澳门葡京】Server触发器及触发器中的事务,数据库事务回滚的用法。PRIMARY]

业务并发

对此sql.Tx对象,因为业务进度唯有2个老是,事务内的操作都以种种施行的,在早先下3个数据库交互以前,必须先形成上三个数据库交互。例如上边的事例:

rows, _ := db.Query("SELECT id FROM user") for rows.Next() { var mid, did int rows.Scan db.QueryRow("SELECT id FROM detail_user WHERE master = ?", mid).Scan }

调用了Query方法之后,在Next方法中取结果的时候,rows是维护了2个接连,再度调用QueryRow的时候,db会再从连接池抽出2个新的接二连三。rows和db的连天两者可以存活,并且相互不影响。

不过,这样逻辑在事务管理元帅会失灵:

rows, _ := tx.Query("SELECT id FROM user")for rows.Next() { var mid, did int rows.Scan tx.QueryRow("SELECT id FROM detail_user WHERE master = ?", mid).Scan}

tx实行了Query方法后,连接转移到rows上,在Next方法中,tx.QueryRow将尝试获得该连接举办数据库操作。因为还未曾调用rows.Close,由此底层的一连属于busy状态,tx是无能为力再展开查询的。上边的例子看起来有个别傻,毕竟涉及那样的操作,使用query的join语句就能逃脱那个主题材料。例子只是为了表明tx的行使难题。

     在下边包车型客车内容,用到一些SQL Server
触发器和作业的片段术语,假若稍微不清楚的地点,能够查看MSDN资料库,或SQL
Server本地支持文书档案:

Use TestDB
SET XACT_ABORT ON -- 打开
Begin TransAction
    Insert Into Person(PersonId,PersonName)
                Values('1','Name1')
    Insert Into Person(PersonId,PersonName)
                Values('1','Name1')
    Insert Into Person(PersonId,PersonName)
                Values('3','Name3')
Commit TransAction
/*
    当 SET XACT_ABORT 为 ON 时,
    如果执行 Transact-SQL 语句产生运行时错误,
    则整个事务将终止并回滚。 
    默认情况下它是OFF状态。
*/

997755.com澳门葡京 2😉

实践

前边对事情解释了一群,说了那么多,其实还不比share的code。上边就事情的运用做简单的牵线。因为业务是单个连接,因而任何事务管理进程的出现了要命,都亟待运用rollback,1方面是为着保障数据完整1致性,另壹方面是释放专门的学问绑定的连日。

func doSomething(){ panic("A Panic Running Error")}func clearTransaction(tx *sql.Tx){ err := tx.Rollback() if err != sql.ErrTxDone && err != nil{ log.Fatalln }}func main() { db, err := sql.Open("mysql", "root:@tcp(127.0.0.1:3306)/test?parseTime=true") if err != nil { log.Fatalln } defer db.Close() tx, err := db.Begin() if err != nil { log.Fatalln } defer clearTransaction rs, err := tx.Exec("UPDATE user SET gold=50 WHERE real_name='vanyarpy'") if err != nil { log.Fatalln } rowAffected, err := rs.RowsAffected() if err != nil { log.Fatalln } fmt.Println(rowAffected) rs, err = tx.Exec("UPDATE user SET gold=150 WHERE real_name='noldorpy'") if err != nil { log.Fatalln } rowAffected, err = rs.RowsAffected() if err != nil { log.Fatalln } fmt.Println(rowAffected) doSomething() if err := tx.Commit(); err != nil { // tx.Rollback() 此时处理错误,会忽略doSomthing的异常 log.Fatalln }}

大家定义了1个clearTransaction函数,该函数会实行rollback操作。因为大家事务管理进度中,任何两个张冠李戴都会产生main函数退出,因而在main函数退出实践defer的rollback操作,回滚事务和刑释连接。

万1不增加defer,只在最后Commit后check错误err后再rollback,那么当doSomething发生特别的时候,函数就退出了,此时还没有举办到tx.Commit。那样就导致工作的总是未有安息,事务也从没回滚。

  • DML触发器(DML Triggers)
  • DDL触发器(DDL Triggers)
  • 专门的学问情势(Transaction modes)
  • 显式事务(Explicit Transactions)
  • 活动提交业务(Autocommit Transactions)
  • 隐式事务(Implicit Transactions)
  • 批范围的事务(Batch-scoped Transactions)

全副回滚方法二:使用Try…Catch

 

总结

database/sql提供了事务管理的成效。通过Tx对象完成。db.Begin会创设tx对象,后者的Exec和Query实施专业的数据库操作,最终在tx的Commit和Rollback中做到数据库事务的交给和回滚,同时释放连接。

tx事务情形中,唯有一个数据库连接,事务内的Eexc都以逐一实行的,事务中也得以行使db举行询问,不过db查询的长河会新建连接,这几个延续的操作不属于该事情。

有关database/sql和mysql的驱动,大家早就分叁有个别内容介绍了。下1节,将会对后边的内容实行梳理计算,包含错误管理和注意事项的补偿。

After触发器 Vs Instead Of触发器

            After 触发器将要管理触发操作(Insert、Update 或
Delete)、Instead Of 触发器和平条目束之后激发。Instead
Of是将在管理约束前激发,以代表触发操作。上边两张图描述了After触发器和Instead
Of触发器的实施先后顺序。

    
997755.com澳门葡京 3      
997755.com澳门葡京 4 

    
图1                                                                            
图2

    
右边的图一,描述了After触发器施行各种情状,小编在此地通过1个简短的事例来表明After触发器的执行各种,以便能强化对左图一After触发器的领会。

先创建表Contact

use tempdb

Go

if object_id('Contact') Is Not null 

    Drop Table Contact

Go

Create Table Contact

(

    ID int Primary Key Identity(1,1),

    Name nvarchar(50),

    Sex nchar(2) Check(Sex In(N'F',N'M')) Default('M')

)

Go

再创建After触发器tr_Contact

use tempdb

Go

If Exists(Select 1 From sys.triggers Where name='tr_Contact')

    Drop  Trigger tr_Contact 

Go

Create Trigger     tr_Contact On Contact After Insert

As

Select Name,Sex From Inserted /*显示Inserted表的内容,用来判断触发器执行的先后顺序*/

Go

下一场Insert数据,判定After触发器的进行顺序

use tempdb

Go

Insert Into Contact (Name,Sex) Values ('Bill','U')

Go

此地,在并未有运转Insert语句在此之前,我们得以判明,实施Insert进度会触发Check错误,因为字段Sex的值必须是”F”
Or “M”,而那边将在插入的是”U”.好了,再来看运营Insert语句后的场馆。

997755.com澳门葡京 5

本例子,只见到引发Check约束争辩的一无所长,而壹筹莫展看出Inserted表的数量,表明一(Wissu)些正是,引起Check约束在此以前,不会抓住After触发器tr_Contact的操作。那就证实了图一的After触发器施行各类情状。

     好了,接下去,我们再测试Instead Of触发器
图二的场所;小编动用下边建好的测试表Contact来比喻。

先修改触发器tr_Contact内容,

use tempdb

Go

If Exists(Select 1 From sys.triggers Where name='tr_Contact')

    Drop  Trigger tr_Contact 

Go

Create Trigger     tr_Contact On Contact Instead Of Insert

As

print '触发器作代替执行操作'

Insert Into Contact (Name,Sex) Select Name,Sex From Inserted /*代替触发器外面的Insert行为*/

Go

再Insert数据,观望SQL Server实践后的提醒音信,

use tempdb

Go

Insert Into Contact (Name,Sex) Values ('Bill','U')

Go

997755.com澳门葡京 6  

那里,看到,先是触发器操作,再是Check约束处理。本例中,在触发器里面使用一条Insert的语句来描述触发器的取代施行操作,那SQL语句通过Select表Inserted获得触发器外面Insert内容。当SQL
Server实施到触发器里面包车型大巴Insert语句,才会引起Check约束管理.要是,在触发器tr_Contact没有Insert的代表行为,那么就不会现出Check约束管理错误的新闻(注:未有Check错误音讯,并不代表一向不作Check管理)。修改上边包车型大巴触发器tr_Contact内容,做个轻巧的验证.

use tempdb

Go

If Exists(Select 1 From sys.triggers Where name='tr_Contact')

    Drop  Trigger tr_Contact 

Go

Create Trigger     tr_Contact On Contact Instead Of Insert

As

print '触发器作代替执行操作'

Go

use tempdb

Go

Insert Into Contact (Name,Sex) Values ('Bill','U')

Go

Select * From Contact

997755.com澳门葡京 7997755.com澳门葡京 8

能够观察,Instead Of
触发器tr_Contact内容并未有Insert的SQL语句,不会吸引Check管理错误,而且检查Insert动作后的结果,发掘表Contact也从不事先我们Insert的数量。这几个丰富验证了Instead
Of触发器的施行先后顺序和代表实践操作。

 

 

 

DML 触发器 Vs DDL 触发器


      DML 触发器在 Insert、Update 和 Delete 语句上操作,能够当做After
触发器 和 Instead Of 触发器。

     DDL 触发器对 Create、Alter、Drop 和任何 DDL 语句以及执行 DDL
式操作的仓库储存进度实践操作,只可看成After触发器,不能够Instead Of触发器。

     后边的始末,有描述DML触发器中的After & Instead
Of触发器内容,下边直接来看DDL的操作顺序:

    
997755.com澳门葡京 9

     图3.

     从图三.足以知晓,在DDL触发器中,是绝非创建Inserted &
Deleted进程的,大家通过轻便的事例去测试下。

     创立2个服务器范围内的DDL触发器,检查有未有Inserted 表,

use master

Go

If Exists(Select 1 From sys.server_triggers Where name='tr_createDataBase')

    Drop Trigger  tr_createDataBase On All Server

Go

Create Trigger tr_createDataBase On All Server After Create_DataBase

As 

Select * From inserted

Go

进行制造数据库SQL语句,

use master

Go

Create Database myDataBase On Primary

(Name='MyDataBase_Data',Filename='E:\DATA\SQL2008DE01\MyDataBase_Data.mdf') Log On 

(Name='MyDataBase_Log',Filename='E:\DATA\SQL2008DE01\MyDataBase_Log.ldf')

Go

回到错误消息,

997755.com澳门葡京 10

行使上边同样的艺术,大家证实DDL触发器中,不会成立Deleted表;是或不是成立Deleted
&
Inserted,也能够以为是DDL触发器与DML触发器差别之处。在DLL触发器与DML触发器不一样的三个最首要特色是功效域,DML触发器只可以采用在数据库层(Database
Level)的表和视图上,而DDL触发器应用于数据库层(Database
Level)和劳务器层(Server
Level);DDL触发器的成效域取决于事件。上边轻巧描述下事件组的内容。

 

数码库层事件非同平常涵盖:

  1. DDL Table events: Create table, Alter table, Drop table
  2. DDL view events : Create view, Alter view, Drop view
  3. DDL trigger events :Create trigger, Drop trigger, Alter trigger
  4. DDL synonym events: Create synonym, drop synonym
  5. DDL Index events: Create index, Alter index, Drop Index
  6. DDL Database level security events:
    • Create User, Drop user, Alter user
    • Create role, Drop role, Alter role
    • Create application role, Drop application role, Alter
      Application role
    • Create Schema, Drop Schema, Alter Schema
    • Grant database access, Revoke database access, Deny Database
      access
  7. DDL Service broker events:
    • Create Message type, Alter Message type, Drop Message type
    • Create contract, Drop contract, Alter contract
    • Create Service, Alter service, Drop Service
    • Create route, Drop route, Alter route

服务器层事件首要含有:

  1. Create Database, Drop Database
  2. Create Login, Drop Login, Alter Login

 

 

触发器和作业的好玩的事


      在后面包车型大巴多少个例证中,如DML触发器例子,Insert
语句实践后,因为触发器操作 或
Check处理错误,未有把多少真正的插入到表Contact中。其实,当施行触发器时,触发器的操作看似有二个未成功的事体在起效果。
通过几个例子来讲课触发器和作业的故事。

创办二个表ContactHIST,用于对表Contact作Update Or
Delete操作时,把操作前的多少Insert到表ContactHIST中。

use tempdb

Go

if object_id('ContactHIST') Is Not null 

    Drop Table ContactHIST

Go

Create Table ContactHIST

(

    ID int Primary Key Identity(1,1),

    ContactID int,

    Name nvarchar(50),

    Sex nchar(2),

    ActionType nvarchar(10) Check(ActionType In('Update','Delete')),

    LastUpdateDate datetime Default(getdate())

)

Go

修改触发器tr_Contact内容,

use tempdb

Go

If Exists(Select 1 From sys.triggers Where name='tr_Contact')

    Drop  Trigger tr_Contact 

Go

Create Trigger     tr_Contact On Contact After Update,Delete

As

Insert Into ContactHIST(ContactID,Name,Sex)

    Select ID,Name,Sex From deleted 

 

Rollback Tran 

 

Begin Tran

Go

测试数据,

use tempdb

Go

Insert Into Contact (Name,Sex) Values ('Bill','F')

Go

--Update

Update Contact 

    Set Sex='M'

    Where Name='Bill'

Go

Select * From Contact

Select * From ContactHIST

Go

测试结果:

997755.com澳门葡京 11997755.com澳门葡京 12

从下面的测试境况,看出,Update
Contact触发tr_Contact触发器操作,触发器里面包车型大巴Rollback Tran
动作导致了触发器外面包车型大巴Update语句试行回滚,而Rollback Tran
语句前面包车型地铁Begin
Tran语句,重借使运用于保持整个专门的职业的完整性。为了更能驾驭那1过程,作者模拟了三个触发器中的事务伊始终结进度。

997755.com澳门葡京 13

图4.

在SQL Server 200伍 和 SQL Server
二零一零上边,能够见见如图四.的效益。在低版本的SQL
Server上,或者会出现谬误提示情状,不管什么样,在触发器外面,SQL
Server都会Rollback Tran。上边笔者做个谬误提示的例证。

修改触发器tr_Contact内容

use tempdb

Go

If Exists(Select 1 From sys.triggers Where name='tr_Contact')

    Drop  Trigger tr_Contact 

Go

Create Trigger     tr_Contact On Contact After Update,Delete

As

Insert Into ContactHIST(ContactID,Name,Sex)

    Select ID,Name,Sex From deleted 

 

Rollback Tran 

 

--Begin Tran 

Go

双重试行Update操作,

use tempdb

Go

Update Contact 

    Set Sex='M'

    Where Name='Bill'

Go    

Select @@TRANCOUNT    

Go

Select * From Contact

Select * From ContactHIST

Go

997755.com澳门葡京 14997755.com澳门葡京 15

在触发器里面未有Begin
Tran语句动作,触发器外面也能回滚操作。那里大家可以通过查询表数据和@@Trancount来决断。

         其实,上边包车型客车例子,Update语句,是以机关提交业务(Autocommit
Transactions)格局 伊始举行的,触发器里Rollback Tran前面,不管有未有Begin
Tran ,最后都会事务都会交回给SQL
Server自动提交事务管理。当然,在DML触发器中,你能够行使显式事务(Explicit
Transactions),或开启隐式事务(Implicit Transactions)
来决定,当然你也得以动用于批范围的事体(Batch-scoped Transactions)
中。那里,笔者通过开启隐式事务(Implicit Transactions)
的事例来说,触发器与作业的关联。

修改触发器tr_Contact的内容,

use tempdb

Go

If Exists(Select 1 From sys.triggers Where name='tr_Contact')

    Drop  Trigger tr_Contact 

Go

Create Trigger     tr_Contact On Contact After Update,Delete

As

Print N'触发器里Insert 前,@@Trancount='+Rtrim(@@Trancount)

 

Insert Into ContactHIST(ContactID,Name,Sex)

    Select ID,Name,Sex From deleted 

 

Print N'触发器里Insert后,Rollback Tran 前,@@Trancount='+Rtrim(@@Trancount)

 

Rollback Tran 

 

Print N'触发器里Rollback Tran 后,@@Trancount='+Rtrim(@@Trancount)

 

Begin Tran 

Go

开启隐式事务(Implicit Transactions) 来测试,

use tempdb

Go

Set Implicit_transactions On /**/

Go

Print N'Update Contact前,@@Trancount='+Rtrim(@@Trancount)

 

Update Contact 

    Set Sex='M'

    Where Name='Bill'



Print N'Update Contact后,@@Trancount='+Rtrim(@@Trancount)

 

Rollback Tran

 

Print N'触发器外面Rollback Tran 后,@@Trancount='+Rtrim(@@Trancount)



Go    

Set Implicit_transactions Off /**/

Go

 

Go

Select * From Contact

Select * From ContactHIST

Go

 

997755.com澳门葡京 16

 

那里,你是否开采3个很有趣的难题,在触发器理,推行Insert
ContactHIST在此之前,@@Trancount=一,实践Insert后,@@Trancount还是为一,触发器外面Update
Contact后,@@Trancount就成为了二,。那里能够知道成,你在触发器里面,发出2个Begin
Tran,那么SQL Server 就会创造三个嵌套事务。当您在触发器里面,在Rollback
Tran后边屏蔽掉Begin Tran,就会合世错误360玖,如,

use tempdb

Go

If Exists(Select 1 From sys.triggers Where name='tr_Contact')

    Drop  Trigger tr_Contact 

Go

Create Trigger     tr_Contact On Contact After Update,Delete

As

Print N'触发器里Insert 前,@@Trancount='+Rtrim(@@Trancount)

 

Insert Into ContactHIST(ContactID,Name,Sex)

    Select ID,Name,Sex From deleted 

 

Print N'触发器里Insert后,Rollback Tran 前,@@Trancount='+Rtrim(@@Trancount)

 

Rollback Tran 

 

Print N'触发器里Rollback Tran 后,@@Trancount='+Rtrim(@@Trancount)

 

Go

 

997755.com澳门葡京 17

此间,能够看看事情在触发器中Rollback,又尚未张开新的政工,导致整个批管理就半涂而废,不会继续实践触发器外面包车型大巴Rollback
Tran操作。倘若,你在触发器中动用Begin Tran …… Commit
Tran格式,那么触发器Commit
Tran不会潜移默化到外边的业务;上面描述三种广泛触发器吉林中华南电影学院程公司作的动静:

997755.com澳门葡京 18997755.com澳门葡京 19997755.com澳门葡京 20

图5.                                                                            
图6.                                                                          
图7.

图5.叙述在触发器中隐含Begin Tran …… Commit Tran的意况,

图陆.叙述在触发器中包括Save Tran savepoint_name …… Rollback Tran
savepoint_name 的情况,触发器中的Rollback Tran
只会回滚内定的保存点,不会影响到触发器外面包车型大巴Commit Tran Or Rollback
Tran操作。

图柒.叙述在触发器中包涵Rollback Tran的景观,不管触发器里面有未有Begin
Tran,都会油可是生错误360九,中止批管理。

   
注:DDL触发器操作能够触发器中回滚操作,能够应用命令如Rollback,但严重错误恐怕会促成整个业务自动回滚。无法回滚发生在
DDL 触发器正文内的 Alter Database事件。在触发器中运用Rollback … Begin
Tran
大概会招致意外的结果,在一向不认可和测试意况下,请不要随意在触发器中平素运用Rollback
…Begin Tran管理格局.尤其是Create Database事件,在SQL Server 2010和SQL
Server 二零零七条件下,爆发的结果差异。

Rollback …Begin Tran情况:

Create Trigger ….

As

……

Rollback

Begin Tran

End

小结


 

     回看前文至后文,从After触发器VsInstead Of 触发器,说起DML触发器 Vs
DDL触发器,再到触发器广东中华南理哲高校程集团作的传说。只怕有个别地方描述的多少模糊,有个别地点唯有一笔带过;你在测试代码过程中,也许发现有些地点与那里测试的情形各异,那只怕是因为SQL
Server版本的两样,导致一些测试结果不一样。无论怎么着,只要你认为对您打探触发器,有个别拉拉扯扯,就OK了。

     

Use TestDB
Begin Try
    Begin TransAction
        Insert Into Person(PersonId,PersonName)
                    Values('1','Name1')
        Insert Into Person(PersonId,PersonName)
                    Values('1','Name1')
        Insert Into Person(PersonId,PersonName)
                    Values('3','Name3')
    Commit TransAction
End Try
Begin Catch
    Rollback TransAction
End Catch
/*
    使用TryCatch来捕获异常。
    如果 TRY 块内生成的错误导致当前事务的状态失效,
    则将该事务归类为不可提交的事务。
    如果通常在 TRY 块外中止事务的错误在 TRY 内发生时,
    就会导致事务进入不可提交状态。
    不可提交的事务只能执行读操作或 ROLLBACK TRANSACTION。
    该事务不能执行任何可能生成写操作或 COMMIT TRANSACTION 的 Transact-SQL 语句。
    如果事务被分类为不可提交的事务,则 XACT_STATE 函数会返回值 -1。
*/

 

全副回滚方法叁:自定义错误变量

默许境况下一旦推行四个作业中冒出谬误,则只回滚错误操作语句(正是说那句不进行了,算不上回滚),错误处在此之前或之后的不错操作语句还是会被交付。如:

Use TestDB
Declare @tranError int -- 定义变量
Set @tranError=0
    Begin TransAction
        Insert Into Person(PersonId,PersonName)
                    Values('1','Name1')
            Set @tranError = @tranError + @@Error
        Insert Into Person(PersonId,PersonName)
                    Values('1','Name1')
            Set @tranError = @tranError + @@Error
        Insert Into Person(PersonId,PersonName)
                    Values('3','Name3')
            Set @tranError = @tranError + @@Error
    If @tranError = 0
        Commit TransAction
    Else
        Rollback TransAction
/*
    自定义一个变量来判断最后是否发生过错误。
*/

997755.com澳门葡京 21😉

聊到底要专注的是:假使3个业务写了 Begin TransAction 而没写 Commit TransAction 或 Rollback TransAction 则相关操作的数额(只怕是表,也许是列,那自身还没测试。。。)会被锁住。。。而对此锁住的化解办法正是独自推行一下Commit TransAction 或 Rollback TransAction

Use
TestDB

Begin TransAction
    Insert Into
Person(PersonId,PersonName)
                Values(‘1′,’Name1’)
    Insert Into
Person(PersonId,PersonName)
                Values(‘1′,’Name1’)
    Insert Into
Person(PersonId,PersonName)
                Values(‘3′,’Name3’)
Commit TransAction
/*
    Select 一下 有’1′,’Name1’和’3′,’Name3’,
    表达唯有第2句的失实被吊销了
*/

997755.com澳门葡京 22😉

 

总体回滚的办法一:展开 XACT_ABORT

997755.com澳门葡京 23😉

Use
TestDB
SET XACT_ABORT ON —
打开
Begin TransAction
    Insert Into
Person(PersonId,PersonName)
                Values(‘1′,’Name1’)
    Insert Into
Person(PersonId,PersonName)
                Values(‘1′,’Name1’)
    Insert Into
Person(PersonId,PersonName)
                Values(‘3′,’Name3’)
997755.com澳门葡京 ,Commit TransAction
/*
    当 SET XACT_ABORT 为 ON 时,
    假设实施 Transact-SQL 语句产生运营时不当,
    则整个业务将告一段落并回滚。
    暗中认可情形下它是OFF状态。
*/

997755.com澳门葡京 24😉

 

一切回滚方法二:使用Try…Catch

997755.com澳门葡京 25😉

Use
TestDB
Begin Try
    Begin TransAction
        Insert Into
Person(PersonId,PersonName)
                    Values(‘1′,’Name1’)
        Insert Into
Person(PersonId,PersonName)
                    Values(‘1′,’Name1’)
        Insert Into
Person(PersonId,PersonName)
                    Values(‘3′,’Name3’)
    Commit TransAction
End Try
Begin Catch
    Rollback TransAction
End Catch
/*
   
使用Try997755.com澳门葡京 26Catch来捕获卓殊。
    借使 TOdysseyY 块内生成的谬误造成当前政工的景况失效,
    则将该职业归类为不可提交的作业。
    若是平日在 TRY 块外中止事务的谬误在 T奥德赛Y 内产生时,
    就会促成事情进入不可提交状态。
    不可提交的事务只可以施行读操作或 ROLLBACK TRANSACTION。
    该专门的学问无法实行其它可能生成写操作或 COMMIT TRANSACTION 的
Transact-SQL 语句。
    假设专门的职业被分门别类为不可提交的事情,则 XACT_STATE 函数会重回值 -一。
*/

997755.com澳门葡京 27😉

 

万事回滚方法3:自定义错误变量

997755.com澳门葡京 28😉

Use
TestDB
Declare @tranError int —
定义变量
Set @tranError=0
    Begin TransAction
        Insert Into
Person(PersonId,PersonName)
                    Values(‘1′,’Name1’)
            Set @tranError = @tranError + @@Error
        Insert Into
Person(PersonId,PersonName)
                    Values(‘1′,’Name1’)
            Set @tranError = @tranError + @@Error
        Insert Into
Person(PersonId,PersonName)
                    Values(‘3′,’Name3’)
            Set @tranError = @tranError + @@Error
    If @tranError = 0
        Commit TransAction
    Else
        Rollback TransAction
/*
    自定义三个变量来判别最后是否产生过荒唐。
*/

997755.com澳门葡京 29😉

 

 

终极要留意的是:如若贰个事情写了 Begin TransAction 而没写 Commit
TransAction 或 Rollback TransAction
则相关操作的数据(只怕是表,也许是列,那自个儿还没测试。。。)会被锁住。。。而对此锁住的化解办法便是单身实行一下Commit
TransAction 或 Rollback TransAction

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website