转自:http://blog.csdn.net/chinajiyong/article/details/7280690
在MSSQL中,尽管系统中发生错误,SQL SERVER仍然维持每个数据库的一致性和完整性。每个更新SQL Server数据库内数据的应用程序都使用事务完成这个任务。事务是由一系列语句(选择、插入、更新或删除)构成的逻辑工作单元。如果在事务执行过程中没有遇到错误,则事务中的所有修改成为数据库的永久部分。如果遇到错误,则不对数据库做任何修改。
事务经历下面几个阶段:
1、事务启动前,数据库处于一致状态。
2、应用程序发出启动事务的信号。这可以通过 BEGIN TRANSACTION 语句显式完成。或者,应用程序也可以设置在隐性事务模式下运行的选项;使新事务由前面的事务完成后所执行的第一个Transact-SQL语句自动启动。此时不向日志写入记录;当应用程序为数据修改生成第一个日志记录时,才向日志写入第一个记录。
3、应用程序开始修改数据。一次只修改一个表中的数据。随着一系列的修改,数据库可能会处于暂时不一致的中间状态。
4、当应用程序执行到全部修改均已成功完成且数据库再次处于一致状态时,应用程序提交事务。这使全部修改成为数据库的永久部分。
5、如果应用程序遇到一些防碍事务完成的错误,则撤消或回滚所有数据修改。这将使数据库返回到事务启动前所处于的一致状态。
SQL Server应用程序还可以在自动提交模式下运行。在自动提交模式下,如果成功则自动提交各个Transact-SQL语句,如果生成错误则自动回滚各个Transact-SQL语句。在自动提交模式下运行的应用程序不需要发出专门启动或结束事务的语句。
所有的Transact-SQL语句都在下列事务中运行:显式事务、隐性事务或自动提交事务。所有包含数据修改的SQL Server事务要么到达新的一致点并提交,要么回滚到原始的一致点。事务不会被留在使数据库不一致的中间状态中。
下面针对事务举一个示例:
首先,我们创建一个银行信息表
- IF OBJECT_ID('bankInfo') IS NOT NULL
- DROP TABLE bankInfo
- GO
- --银行卡信息表
- CREATE TABLE bankInfo
- (
- uId VARCHAR(18) NOT NULL PRIMARY KEY,--卡号
- uName VARCHAR(20), --卡主姓名
- uMoney MONEY --卡中余额
- )
- GO
- INSERT INTO bankInfo VALUES('9559901','张三',1)
- INSERT INTO bankInfo VALUES('9559902','李四',1000)
- INSERT INTO bankInfo VALUES('9559903','王五',800)
- INSERT INTO bankInfo VALUES('9559904','赵六',50)
- INSERT INTO bankInfo VALUES('9559905','赵明',5)
- SELECT * FROM bankInfo,结果显示如下:
- /*
- uId uName uMoney
- ------------------ -------------------- ---------------------
- 9559901 张三 1.00
- 9559902 李四 1000.00
- 9559903 王五 800.00
- 9559904 赵六 50.00
- 9559905 赵明 5.00
- (5 行受影响)
- */
那么我们不使用事务来完成,我们会写下面这样的sql语句来完成:
- UPDATE bankInfo SET uMoney=uMoney-400 WHERE uId='9559902'
- UPDATE bankInfo SET uMoney=uMoney+400 WHERE uId='9559901'
- SELECT * FROM bankInfo,查询结果如下:
- /*
- uId uName uMoney
- ------------------ -------------------- ---------------------
- 9559901 张三 401.00
- 9559902 李四 600.00
- */
PRINT '转账前的余额:'
SELECT * FROM bankInfo
使用如下sql语句
- ------begin transaction---------开始事务
- SET IMPLICIT_TRANSACTIONS ON
- DECLARE @myerror INT --用于存储错误号
- SET @myerror=0
- UPDATE bankInfo SET uMoney=uMoney-800 WHERE uId='9559902'
- SET @myerror=@myerror+@@ERROR --如果产生错误,则将错误号累加
- UPDATE bankInfo SET uMoney=uMoney+800 WHERE uId='9559901'
- SET @myerror=@myerror+@@ERROR --如果产生错误,则将错误号累加
- IF @myerror>0 --如果执行过程出错
- BEGIN
- PRINT '转账失败,正准备回滚事务!'
- ROLLBACK TRANSACTION
- END
- ELSE --如果过程中没有出现问题
- BEGIN
- PRINT '转账成功,准备提交事务!'
- COMMIT TRANSACTION
- END
- ------end transaction---------结束事务
- PRINT '转账后的余额'
- SELECT * FROM bankInfo
- 查询结果如下:
- /*
- uId uName uMoney
- ------------------ -------------------- ---------------------
- 9559901 张三 401.00
- 9559902 李四 600.00
- */