转自:

http://www.cnblogs.com/moss_tan_jun/archive/2011/11/26/2263988.html

 

  • 事务

在数据库中有时候需要把多个步骤的指令当作一个整体来运行,这个整体要么全部成功,要么全部失败,这就需要用到事务。

1. 事务的特点

事务由若干条T-SQL指令组成,并且所有的指令作为一个整体提交给数据库系统,执行时,这组指令要么全部执行完成,要么全部取消。因此,事务是一个不可分割的逻辑单元。

事务有4个属性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)以及持久性(Durability),也称作事务的ACID属性。

原子性:事务内的所有工作要么全部完成,要么全部不完成,不存在只有一部分完成的情况。

一致性:事务内的然后操作都不能违反数据库的然后约束或规则,事务完成时有内部数据结构都必须是正确的。

隔离性:事务直接是相互隔离的,如果有两个事务对同一个数据库进行操作,比如读取表数据。任何一个事务看到的所有内容要么是其他事务完成之前的状态,要么是其他事务完成之后的状态。一个事务不可能遇到另一个事务的中间状态。

持久性:事务完成之后,它对数据库系统的影响是持久的,即使是系统错误,重新启动系统后,该事务的结果依然存在。

2. 事务的模式

a. 显示事务

显示事务就是用户使用T-SQL明确的定义事务的开始(begin transaction)和提交(commit transaction)或回滚事务(rollback transaction)

b. 自动提交事务

自动提交事务是一种能够自动执行并能自动回滚事务,这种方式是T-SQL的默认事务方式。例如在删除一个表记录的时候,如果这条记录有主外键关系的时候,删除就会受主外键约束的影响,那么这个删除就会取消。

可以设置事务进入隐式方式:set implicit_transaction on;

c. 隐式事务

隐式事务是指当事务提交或回滚后,SQL Server自动开始事务。因此,隐式事务不需要使用begin transaction显示开始,只需直接失业提交事务或回滚事务的T-SQL语句即可。

使用时,需要设置set implicit_transaction on语句,将隐式事务模式打开,下一个语句会启动一个新的事物,再下一个语句又将启动一个新事务。

3. 事务处理

常用T-SQL事务语句:

a. begin transaction语句

开始事务,而@@trancount全局变量用来记录事务的数目值加1,可以用@@error全局变量记录执行过程中的错误信息,如果没有错误可以直接提交事务,有错误可以回滚。

b. commit transaction语句

回滚事务,表示一个隐式或显示的事务的结束,对数据库所做的修改正式生效。并将@@trancount的值减1;

c. rollback transaction语句

回滚事务,执行rollback tran语句后,数据会回滚到begin tran的时候的状态

4. 事务的示例

--开始事务
begin transaction tran_bank;
declare @tran_error int;
set @tran_error = 0;
begin try
update bank set totalMoney = totalMoney - 10000 where userName = 'jack';
set @tran_error = @tran_error + @@error;
update bank set totalMoney = totalMoney + 10000 where userName = 'jason';
set @tran_error = @tran_error + @@error;
end try
begin catch
print '出现异常,错误编号:' + convert(varchar, error_number()) + ', 错误消息:' + error_message();
set @tran_error = @tran_error + 1;
end catch
if (@tran_error > 0)
begin
--执行出错,回滚事务
rollback tran;
print '转账失败,取消交易';
end
else
begin
--没有异常,提交事务
commit tran;
print '转账成功';
end
go
 
  • 异常

在程序中,有时候完成一些Transact-SQL会出现错误、异常信息。如果我们想自己处理这些异常信息的话,需要手动捕捉这些信息。那么我们可以利用try catch完成。

TRY…CATCH 构造包括两部分:一个 TRY 块和一个 CATCH 块。如果在 TRY 块中所包含的 Transact-SQL 语句中检测到错误条件,控制将被传递到 CATCH 块(可在此块中处理该错误)。

CATCH 块处理该异常错误后,控制将被传递到 END CATCH 语句后面的第一个 Transact-SQL 语句。如果 END CATCH 语句是存储过程或触发器中的最后一条语句,控制将返回到调用该存储过程或触发器的代码。将不执行 TRY 块中生成错误的语句后面的 Transact-SQL 语句。

如果 TRY 块中没有错误,控制将传递到关联的 END CATCH 语句后紧跟的语句。如果 END CATCH 语句是存储过程或触发器中的最后一条语句,控制将传递到调用该存储过程或触发器的语句。

TRY 块以 BEGIN TRY 语句开头,以 END TRY 语句结尾。在 BEGIN TRY 和 END TRY 语句之间可以指定一个或多个 Transact-SQL 语句。CATCH 块必须紧跟 TRY 块。CATCH 块以 BEGIN CATCH 语句开头,以 END CATCH 语句结尾。在 Transact-SQL 中,每个 TRY 块仅与一个 CATCH 块相关联。

错误函数

TRY...CATCH 使用错误函数来捕获错误信息:

ERROR_NUMBER() 返回错误号。
ERROR_MESSAGE() 返回错误消息的完整文本。此文本包括为任何可替换参数(如长度、对象名称或时间)提供的值。
ERROR_SEVERITY() 返回错误严重性。
ERROR_STATE() 返回错误状态号。
ERROR_LINE() 返回导致错误的例程中的行号。
ERROR_PROCEDURE() 返回出现错误的存储过程或触发器的名称。

 

示例

错误消息存储过程

if (object_id('proc_error_info') is not null)
drop procedure proc_error_info
go
create proc proc_error_info
as
select
error_number() '错误编号',
error_message() '错误消息',
error_severity() '严重性',
error_state() '状态好',
error_line() '错误行号',
error_procedure() '错误对象(存储过程或触发器)名称';
go

示例:用异常处理错误信息

简单try catch示例
begin try
select 1 / 0;
end try
begin catch
exec proc_error_info; --调用错误消息存储过程
end catch
go

示例:异常能处理的错误信息

简单try catch示例,无法处理错误
begin try
select * * from student;
end try
begin catch
exec proc_error_info;
end catch
go
简单try catch示例,不处理错误(不存在的表对象)
begin try
select * from st;
end try
begin catch
exec proc_error_info;
end catch
go
异常处理,能处理存储过程(触发器)中(不存在表对象)的错误信息
if (object_id('proc_select') is not null)
drop procedure proc_select
go
create proc proc_select
as
select * from st;
go
begin try
exec proc_select;
end try
begin catch
exec proc_error_info;
end catch
go 
 
异常不能处理编译期的错误,如语法错误。以及重编译造成部分名称对象得不到正确解析的时候所出现的错误。

示例:无法提交的事务

--创建临时用表
if (object_id('temp_tab', 'u') is not null)
drop table temp_tab
go
create table temp_tab(
id int primary key identity(100000, 1),
name varchar(200)
)
go begin try
begin tran;
--没有createTime字段
alter table temp_tab drop column createTime;
commit tran;
end try
begin catch
exec proc_error_info;--显示异常信息
if (xact_state() = -1)
begin
print '会话具有活动事务,但出现了致使事务被归类为无法提交的事务的错误。'
+ '会话无法提交事务或回滚到保存点;它只能请求完全回滚事务。'
+ '会话在回滚事务之前无法执行任何写操作。会话在回滚事务之前只能执行读操作。'
+ '事务回滚之后,会话便可执行读写操作并可开始新的事务。';
end
else if (xact_state() = 0)
begin
print '会话没有活动事务。';
end
else if (xact_state() = 1)
begin
print '会话具有活动事务。会话可以执行任何操作,包括写入数据和提交事务。';
end
end catch
go

示例:处理异常日志信息

--异常、错误信息表
if (object_id('errorLog', 'U') is not null)
drop table errorLog
go
create table errorLog(
errorLogID int primary key identity(100, 1), --ErrorLog 行的主键。
errorTime datetime default getDate(), --发生错误的日期和时间。
userName sysname default current_user, --执行发生错误的批处理的用户。
errorNumber int, --发生的错误的错误号。
errorSeverity int, --发生的错误的严重性。
errorState int, --发生的错误的状态号。
errorProcedure nvarchar(126), --发生错误的存储过程或触发器的名称。
errorLine int, --发生错误的行号。
errorMessage nvarchar(4000)
)
go --存储过程:添加异常日志信息
if (object_id('proc_add_exception_log', 'p') is not null)
drop proc proc_add_exception_log
go
create proc proc_add_exception_log(@logId int = 0 output)
as
begin
set nocount on;
set @logId = 0;
begin try
if (error_number() is null)
return; if (xact_state() = -1)
begin
print '会话具有活动事务,但出现了致使事务被归类为无法提交的事务的错误。'
+ '会话无法提交事务或回滚到保存点;它只能请求完全回滚事务。'
+ '会话在回滚事务之前无法执行任何写操作。会话在回滚事务之前只能执行读操作。'
+ '事务回滚之后,会话便可执行读写操作并可开始新的事务。';
end
else if (xact_state() = 0)
begin
print '会话没有活动事务。';
end
else if (xact_state() = 1)
begin
print '会话具有活动事务。会话可以执行任何操作,包括写入数据和提交事务。';
end --添加日志信息
insert into errorLog values(getDate(),
current_user, error_number(),
error_severity(), error_state(),
error_procedure(),
error_line(), error_message());
--设置自增值
select @logId = @@identity;
end try
begin catch
print '添加异常日志信息出现错误';
exec proc_error_info;--显示错误信息
return -1;
end catch
end
go --处理异常信息示例
declare @id int;
begin try
begin tran;
--删除带有外键的记录信息
delete classes where id = 1;
commit tran;
end try
begin catch
exec proc_error_info;--显示错误信息
if (xact_state() <> 0)
begin
rollback tran;
end
exec proc_add_exception_log @id output
end catch
select * from errorLog where errorLogID = @id;
go

SQL Server 事务、异常的更多相关文章

  1. 网络异常与SQL Server事务

    SQL Server事务遭遇网络异常时的处理机制浅析 SQL Server数据库中,如果应用程序正在执行一个事务的时候突然遭遇了网络异常,例如网络掉包,网络中断等,那么这个事务会怎么样? SQL Se ...

  2. 【SqlServer系列】浅谈SQL Server事务与锁(上篇)

    一  概述 在数据库方面,对于非DBA的程序员来说,事务与锁是一大难点,针对该难点,本篇文章视图采用图文的方式来与大家一起探讨. “浅谈SQL Server 事务与锁”这个专题共分两篇,上篇主讲事务及 ...

  3. SQL Server事务回滚对自增键的影响

    SQL Server事务回滚时是删除原先插入导致的自增值,也就是回滚之前你你插入一条数据导致自增键加1,回滚之后还是加1的状态 --如果获取当前操作最后插入的identity列的值:select @@ ...

  4. 为什么说JAVA中要慎重使用继承 C# 语言历史版本特性(C# 1.0到C# 8.0汇总) SQL Server事务 事务日志 SQL Server 锁详解 软件架构之 23种设计模式 Oracle与Sqlserver:Order by NULL值介绍 asp.net MVC漏油配置总结

    为什么说JAVA中要慎重使用继承   这篇文章的主题并非鼓励不使用继承,而是仅从使用继承带来的问题出发,讨论继承机制不太好的地方,从而在使用时慎重选择,避开可能遇到的坑. JAVA中使用到继承就会有两 ...

  5. 浅谈SQL Server事务与锁(上篇)

    一  概述 在数据库方面,对于非DBA的程序员来说,事务与锁是一大难点,针对该难点,本篇文章试图采用图文的方式来与大家一起探讨. “浅谈SQL Server 事务与锁”这个专题共分两篇,上篇主讲事务及 ...

  6. 人人都是 DBA(VI)SQL Server 事务日志

    SQL Server 的数据库引擎通过事务服务(Transaction Services)提供事务的 ACID 属性支持.ACID 属性包括: 原子性(Atomicity) 一致性(Consisten ...

  7. SQL Server事务的隔离级别

    SQL Server事务的隔离级别 ########## 数据库中数据的一致性 ########## 针对并发事务出现的数据不一致性,提出了4个级别的解决方法:  隔离级别  第一类丢失更新  脏读 ...

  8. Sql Server 事务隔离级别的查看及更改

    根据自身 Sql Server 的情况来自定义 事务隔离级别,将会更加的满足需求,或提升性能.例如,对于逻辑简单的 Sql Server,完全可以使用 read uncommitted 模式,来减少死 ...

  9. SQL SERVER 事务的使用(tran)

    sql server事务的使用是为了确保数据的一致性. 通常写法 begin tran --sql 语句1 --sql 语句2 --sql 语句3 commit tran 上面写法存在隐患,当操作(增 ...

  10. 理解Sql Server 事务隔离层级(Transaction Isolation Level)

    关于Sql Server 事务隔离级别,百度百科是这样描述的 隔离级别:一个事务必须与由其他事务进行的资源或数据更改相隔离的程度.隔离级别从允许的并发副作用(例如,脏读或虚拟读取)的角度进行描述. 隔 ...

随机推荐

  1. ZeroBraneStudio之支持远程调试

    打开ZBS后,如果需要远程调试得先开启调试服务器:Project->Start Debugger Server 打开之后就可以编辑文件进行测试了.示例代码如下: local ZBS = 'D:/ ...

  2. struts.enable.DynamicMethodInvocation = true 动态方法调用

    default.properties 在Struts 2的核心jar包-struts2-core中,有一个default.properties的默认配置文件.里面配置了一些全局的信息,比如: stru ...

  3. C语言嵌入式系统编程修炼之五:键盘操作

    处理功能键 功能键的问题在于,用户界面并非固定的,用户功能键的选择将使屏幕画面处于不同的显示状态下.例如,主画面如图1:图1 主画面 当用户在设置XX上按下Enter键之后,画面就切换到了设置XX的界 ...

  4. Android开源项目发现--- 工具类图片缓存篇(持续更新)

    1. Android-Universal-Image-Loader 图片缓存 目前使用最广泛的图片缓存,支持主流图片缓存的绝大多数特性. 项目地址:https://github.com/nostra1 ...

  5. 利用row_number over 函数删除重复记录

    开窗函数                Oracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是:对于每个组返回多行,而聚合函数对于每个组只返回一行 SQ ...

  6. Node.js权威指南 (10) - Node.js中的错误处理与断言处理

    10.1 使用domain模块处理错误 / 272 10.1.1 domain模块概述 / 272 10.1.2 创建并使用Domain对象 / 274 10.1.3 隐式绑定与显式绑定 / 276 ...

  7. 让DataGridView的标题显示中文

    一般情况,DataTable中用来区分不同列的值,使用DataTable.Columns.ColumnsName,但是DataTable的Columns还有一个Caption属性,在这个属性里面可以用 ...

  8. 游戏开发设计模式之状态模式 & 有限状态机 & c#委托事件(unity3d 示例实现)

    命令模式:游戏开发设计模式之命令模式(unity3d 示例实现) 对象池模式:游戏开发设计模式之对象池模式(unity3d 示例实现) 原型模式:游戏开发设计模式之原型模式 & unity3d ...

  9. unity3d shader之God Ray上帝之光

    又是一个post-process后期效果,god ray 上帝之光,说起上帝之光就是咱们再看太阳时太阳周围一圈的针状光芒先放组效果,本文的场景资源均来自浅墨大神,效果为本文shader效果 加入了前篇 ...

  10. Unity3d 基于物理渲染Physically-Based Rendering之最终篇

    前情提要: 讲求基本算法 Unity3d 基于物理渲染Physically-Based Rendering之specular BRDF plus篇 Unity3d 基于物理渲染Physically-B ...