`

在SQL Server存储过程里管理Transactions

阅读更多

本文英文原版及代码下载:
http://www.4guysfromrolla.com/webtech/080305-1.shtml

在SQL Server存储过程里管理Transactions

导言:
上周的文章《Maintaining Database Consistency with Transactions》里我们探讨了到底什么是transactions,以及当对多个数据表发出命令时,是如何确保数据库的数据一致性的.具体的说,transactions确保一系列modifying statement的“原子性”,也就是所有的步骤要么都成功要么都失败.Transactions确保原子数(atomicity)抵御这些威胁:当删除一条记录时因为一个外键约束而无法删除,或试图将一个string值插入到某个数据库表的一numeric列里——还比如一些灾难性的错误,如断电、硬盘驱动器发生碰撞等等。简单的说,当把多个modifying command封装到一个transaction里的时候,执行后的数据库状态将只会为如下2者之一:要么执行失败而回到执行命令之前的状态,要么所有的命令都执行成功——除此外没有中间状态(in-between' state).

典型的事务示例是在不同的帐户之间转账。该过程包括2个步骤:从一个帐户上扣除金额,然后添加到另一个帐户上.我们要避免的是完成了第一步后,因为比如断电等的原因而第二步执行失败.

除了探讨使用transaction的目的之外,上周的文章我们还探讨了如何用ADO.NET将多个modifying statements封装到一个transaction里面。具体来说,我们使用到了SqlTransaction 和 SqlConnection类。一个transaction是由调用SqlConnection类的BeginTransaction()开始,而由SqlTransaction对象的 Commit()或Rollback()来提交或回滚.

本文我们将继续探讨transaction,考察如何直接通过存储过程来创建、提交或回滚transaction.在考察使用transaction的T-SQL语法后,我们来探讨在什么时候我们应该选择直接在一个存储过程里使用transaction.


Stored Procedures点滴...

存储过程类似于一个计算机程序的method,可以接受一系列的输入参数,也可以返回数据.在一个存储过程里你可以写一些要执行的T-SQL statement.与ad-hoc SQL statement相比,存储过程有如下的优势:

.在软件层次体系里额外增加了一层来进行封装
.将程序代码与具体的数据相关的细节分隔开来
.增强了安全性,你可以拒绝对数据库里table的访问,而只允许执行web运行程序要用到的存储过程
.提升了性能,因为SQL server能将存储过程要执行的内容进行缓存,相反,如果是使用ad-hoc查询来执行的话每次使用的时候都要重新进行计算.

本文不打算对创建和使用一个存储过程,以及带来的好处进行深入探讨.对存储过程的更多探讨你可以参考Rob Howard的博客《Don't use stored procedures yet? Must be suffering from NIHS (Not Invented Here Syndrome)》,Nathan Pond的文章《Writing a Stored Procedure》详细地探讨了如何在SQL Server里创建存储过程,更多信息你可以查阅msdn的技术文档.


在一个存储过程里创建Transactions

在上篇文章《Maintaining Database Consistency with Transactions》里我们说过,当使用transaction时,一般来说你要使用如下的步骤:

1.明确指出你要开启一个transaction.包含的所有指令从那一刻起都作为逻辑的,原子操作的一部分.
2.发出指令——也就是transaction里包含的那些INSERT, UPDATE, 以及DELETE指令.
3.如果这些指令引发了一个错误,对transaction进行回滚。回滚的作用在于不执行这些指令.
4.如果一切顺利,则提交transaction.完成对数据库的操作.

我们知道在ADO.NET里,这些步骤是这样来完成的:在Try ... Catch语句里通过调用BeginTransaction()方法来调用transaction,如果发生了任何的与SQL相关的错误,我们就应该在Catch语句里通过调SqlTransaction对象的Rollback()方法来回滚transaction;如果没有错误发生的话,就通过Commit()方法来提交transaction.虽然在存储过程里开启、提交、回滚一个transaction与此稍有不同,但总体概念是一样的.

首先,我们需要宣称开始一个transaction,我们可以使用T-SQL命令 BEGIN TRANSACTION来轻松的实现.接下了,我们要发出transaction里封装的一系列的指令,比如INSERT, UPDATE, 和/或 DELETE.

如果你使用的Microsoft SQL Server早于2005版本,那么对每个modifying statement,你都需要检查是否发生了错误,如何是的话,你要对transaction进行回滚并引发一个异常.具体来说,你要检查@@ERROR的值,如果不为0的话,那就说明刚执行的那条指令引发了错误,在这种情况下,你需要调用关键字ROLLBACK来回滚transaction,然后使用RAISERROR来引发一个错误,RAISERROR将终止对存储过程的调用,并对调用的.NET程序引发一个异常.

如果你使用的是Microsoft SQL Server 2005以及更高版本,那么你可以使用TRY...CATCH语句就行了.本文探讨的是
在早于2005版本里的用法,关于对SQL Server 2005如何使用TRY...CATCH语句的问题,请参阅文章《TRY...CATCH in SQL Server 2005: An Easier Approach to Rolling Back Transactions in the Face of an Error》

最后,在存储过程的末尾,如果没有发生错误则提交该transaction,我们可以使用关键字COMMIT来实现.


示例...

下面的代码片段展示了使用一个存储过程来维护数据的一致性.具体来说,有2张相互关联的表Departments和 Employees,我们要用该存储过程来删除某个具体的department.由于每个Employees记录多有一个与Departments表相关联的外键约束。所以,要想从Departments表里删除一条记录的话,必须首先将Employees表里的相关记录删除掉.这是因为我们希望要么将某个部门以及所有的相关人员都删除掉,要么都不删除,所以我们将这2个DELETE statement封装在一个transaction里.

CREATE PROCEDURE DeleteDepartment
(
@DepartmentID int
)
AS

-- This sproc performs two DELETEs. First it deletes all of the
-- department's associated employees. Next, it deletes the department.

-- STEP 1: Start the transaction
BEGIN TRANSACTION

-- STEP 2 & 3: Issue the DELETE statements, checking @@ERROR after each statement
DELETE FROM Employees
WHERE DepartmentID = @DepartmentID

-- Rollback the transaction if there were any errors
IF @@ERROR <> 0
BEGIN
-- Rollback the transaction
ROLLBACK

-- Raise an error and return
RAISERROR ('Error in deleting employees in DeleteDepartment.', 16, 1)
RETURN
END


DELETE FROM Departments
WHERE DepartmentID = @DepartmentID

-- Rollback the transaction if there were any errors
IF @@ERROR <> 0
BEGIN
-- Rollback the transaction
ROLLBACK

-- Raise an error and return
RAISERROR ('Error in deleting department in DeleteDepartment.', 16, 1)
RETURN
END

-- STEP 4: If we reach this point, the commands completed successfully
-- Commit the transaction....
COMMIT

该RAISERROR方法将指定返回到客户端的错误信息,关于RAISERROR的更多信息请参阅技术文档.


事务管理: Stored Procedures or ADO.NET?

本文连同上周的那篇考察使用ADO.NET来管理事务的文章为我们提过了2种途径来为你的数据驱动程序使用事务提供支持.那么我们应该使用哪个方法呢?我自己2种都在用.对于简单的,在编译时很明确的批指令(batch statement),我倾向于使用存储过程.上面的例子就是极好的证明,当从一个数据表里删除记录时连同它的子记录一起删除掉.

不过在有些时候,我们发出了一系列的原子声明(atomic statement),但直到运行的时候才能确定到底该运行哪一个.或者有数量不等的存储过程,需要根据用户的选择来确定调用哪一个.例如,我们用一个CheckBoxList Web控件来列出所有部门的清单,用户自己选择要删除的部门.

在页面回传的时候,我们遍历CheckBoxList的Item项,再调用我们在上面探讨的那个DeleteDepartment存储过程.现在删除每个部门以及相关员工都当做一个事务来对待(因为我们在存储过程里BEGIN TRANSACTION了) ,但是我们希望所有的每个部门删除行为都作为一个atomic statement,换句话说,假定用户选择删除5个部门,如果在删除第4个部门的时候发生了错误,我们希望对前面3个部门的删除操作“失效”.我们可以这样来实现,把对Items collection的循环进行封装,然后在一个transaction里调用DeleteDepartment存储过程.(这就是一个在ADO.NET层和存储过程层都提供transaction支持的例子)

这么一来我们的代码看起来和下面的差不多:

'Create a connection
Dim myConnection As New SqlConnection(myConnString)
myConnection.Open()

'Start the transaction
Dim myTrans As SqlTransaction = myConnection.BeginTransaction()

Dim sql as String = "DeleteDepartment"

Try
'Create the SqlCommand object, specifying the transaction through
'the constructor (along with the SQL string and SqlConnection)
Dim myCommand as New SqlCommand(sql, myConnection, myTrans)

For Each dept as ListItem in CheckBoxListID.Items
'Add the dept.Value to the Parameters collection
myCommand.Parameters.Clear()

myCommand.Parameters.Add("@DepartmentID", dept.Value)

myCommand.ExecuteNonQuery()
Next

'If we reach here, all command succeeded, so commit the transaction
myTrans.Commit

Catch ex as Exception
'Something went wrong, so rollback the transaction
myTrans.Rollback()

Throw 'Bubble up the exception
Finally
myConnection.Close()'Finally, close the connection
End Try

结语:

在前面的文章我们探讨了通过ADO.NET来使用transaction;在本文我们考察了如何直接通过存储过程的T-SQL commands来管理transaction,这2种方法都有自己的优点.对我来说,我在ADO.NET层对transaction进行管理是在这些这种情况下:当需要在编程时反复构建多个transaction,或需要用到其它高级别的逻辑处理(high-level logic)来确定改动哪些实体的时候。而当发出一个简单的、简单明了的请求来改动多个表——比如当从父表删除一条记录时其子记录也需要删除时,我就在存储过程里管理transaction逻辑.当然,你的处理办法可能跟我的不大一样.

祝编程愉快!

分享到:
评论

相关推荐

    Microsoft sql server system clr types 2012

    在SQL Server中,CLR集成允许开发者使用.NET Framework的语言(如C#或VB.NET)编写存储过程、触发器和其他数据库对象,从而提升性能和功能。 描述中提到的“部署查看Windows SQL服务器报表”是指在Windows环境下...

    SQL 面试题目汇总

    4. **内存泄漏(Memory Leak)**:虽然SQL本身不直接处理内存管理,但在数据库服务器运行时,可能会遇到内存泄漏问题,尤其是在使用存储过程或长时间运行的查询时。理解内存管理的基本原理,如缓冲池和内存池,以及...

    sql server 2012 T-SQl基础教程 源码和示例数据库

    本教程专注于Microsoft SQL Server 2012中的Transact-SQL(T-SQL)语言,这是SQL Server的主要查询语言,用于数据操作、查询、存储过程和数据库对象的编程。T-SQL是SQL Server开发者的核心技能,无论你是新手还是...

    基于SQL server 2008数据库的ifix操作记录教程

    SQL Server 2008是一款由Microsoft开发的关系型数据库管理系统,广泛应用于数据存储、管理与分析。ifix则是一个用于SCADA(Supervisory Control and Data Acquisition)系统的接口软件,常用于工业自动化领域的数据...

    sqlserver培训资料

    1. **SQL Server 2000概述 (sql2000a1-overview.ppt)**:这部分内容会介绍SQL Server 2000的基本架构、功能特性以及它在企业级数据库管理系统中的作用。它可能会涵盖数据库的概念、SQL Server的服务组件、管理和开发...

    《21天学通SQL Server》

    这包括对SQL Server Management Studio、SQL Server Configuration Manager等工具的介绍,以及如何创建数据库、表、视图、存储过程等数据库对象的基本操作。 ### 2. SQL语言详解 SQL(Structured Query Language)...

    Querying SQL server 70-461

    学习如何在SQL Server中管理XML数据,包括存储、查询以及数据的转换。 3. 修改数据(Modify Data) 3.1 创建和修改存储过程(Create and Alter Stored Procedures) 存储过程是一种封装一组SQL语句的方法。本节将...

    sql server 2005课件

    在SQL Server 2005中,数据库管理系统(DBMS)提供了丰富的功能,使得开发者和数据库管理员能够高效地管理和操作数据。本课件主要涵盖了四个关键主题:事务视图、T-SQL编程、存储过程和用户自定义函数,以及触发器。...

    SQLServer数据库运维技术.pptx

    SQLServer 数据库运维技术是指在 SQLServer 数据库中进行性能优化、故障诊断和性能监控的一系列技术和方法。本文档主要介绍了 SQLServer 数据库运维技术的相关知识点,包括性能优化概述、性能指标参数、诊断工具、...

    SqlServer无备份下误删数据恢复工具

    在SQL Server数据库环境中,数据是企业的生命线,任何意外的数据丢失都可能导致严重后果。当面临“无备份下误删数据”的情况时,恢复工作显得尤为关键。本篇将详细讲解如何利用特定工具和方法在SQL Server 2012及更...

    《SQL Server语言参考大全》+语法大全

    《SQL Server语言参考大全》与《SQL语法大全》这两份资料是深入了解和学习SQL Server数据库管理系统的重要资源。SQL(Structured Query Language),结构化查询语言,是用于管理关系数据库的标准语言,而SQL Server...

    基于JAVA和SQL SERVER数据库实现的个人财务管理系统.zip

    《基于JAVA和SQL SERVER数据库实现的个人财务管理系统》 个人财务管理系统是一款用于个人或小型企业进行财务管理的应用程序,它能够帮助用户记录收入、支出、资产和负债,提供数据分析,从而帮助用户更好地掌握财务...

    SQLServer 高级篇

    ### SQL Server 高级篇知识点解析 #### 一、约束(Constraints) 在SQL Server中,约束是用来强制...以上是SQL Server 高级篇的主要知识点,掌握这些概念对于深入理解SQL Server及其在企业级应用中的作用至关重要。

    SQL Server教程式

    在IT领域,数据库管理是至关重要的技能之一,而SQL Server作为微软公司开发的关系型数据库管理系统,广泛应用于企业级数据存储和处理。这个“SQL Server教程式”资源显然是为初学者设计的,旨在帮助他们掌握SQL ...

    ATM机模拟系统、SQL Server 2005

    在这个项目中,开发者使用了SQL Server 2005作为数据库管理系统来存储和管理相关的交易数据。下面将详细介绍这个系统的关键组成部分以及SQL Server 2005在其中的角色。 首先,ATM机模拟系统的核心是其数据库设计。...

    Professional SQL Server 2008 Programming

    2. **工具和技术**:第二章“Tool Time”介绍了SQL Server 2008开发和管理过程中必不可少的工具和技术,如SQL Server Management Studio(SSMS)、SQL Server Profiler等,帮助读者掌握高效的数据库开发和维护方法。...

    sqlserver2008数据库实例

    SQL Server 2008是微软公司推出的一款关系型数据库管理系统,它在企业级数据管理、数据存储和分析方面有着广泛的应用。这个“sqlserver2008数据库实例”是专为学习数据库操作设计的实践资源,非常适合初学者掌握SQL...

    手把手教你用SQL server创建企业人事管理系统(精华)1

    在构建企业人事管理系统的过程中,SQL Server是一个常用且强大的数据库管理系统,尤其适合于处理大量数据和实现复杂查询。本文将深入讲解如何使用SQL Server来创建一个高效、稳定且功能完善的人事管理系统。 首先,...

    C#连接SQLServer数据库

    SqlConnection用于建立和管理与SQL Server的连接,SqlCommand则用于执行SQL命令,SqlDataAdapter作为桥梁,负责在数据库和DataSet之间同步数据。 1. **建立连接**: 使用SqlConnection类创建一个连接对象,需要提供...

    Programming Microsoft SQL Server.ppt

    在“配置/工具”章节中,会讲解如何在Windows 2003标准环境下安装SQL Server 2008企业版,并介绍SQLServer 2008试用版的获取途径。课程还会构建一个名为“SQLClass”的数据库,供学员实践操作。此外,课程会涵盖一...

Global site tag (gtag.js) - Google Analytics