Brian F爱
从专注于角图,Web技术以yobet英雄联盟及波特兰的Node.js的Google开发人员专家中学习。
广告 ·ultimatecourses.com.
用终极课程学习角度正确的方式

单个交易中的多个批次

目标创建一个迁移脚本,该脚本使用事务回滚其中一个SQL语句失败的情况下的更改。

问题如果更改表并添加列,然后尝试在遵循的SQL语句中使用新列,则会发现您收到一个错误,表示列不存在。这是因为陈述处于相同的批处理中。

样本问题代码这是一个小型代码段,显示了包含问题的TSQL。这是将位字段添加到现有表的典型示例,将值设置为true(1),然后更新位字段以不允许空值s。

开始交易改变雇员活性钻头;更新雇员活性=1;改变雇员改变活性钻头空值;承诺交易;

那么,我们还有什么可做的?嗯,我们需要使用多个批处理创建单个事务,由Go关键字分隔。

批次

批处理是SQL Server中的一个重要概念。批处理包括在同一执行计划中执行的一系列SQL语句。由TechNet定义:

批处理是一个或多个Transact-SQL语句的组,同时从应用程序同时发送到SQL Server以执行。SQL Server将批处理的语句编译为单个可执行单元,称为执行计划。然后一次执行执行计划中的陈述。

使用TSQL中的关键字将脚本分为多个批次。这解决了迁移脚本的问题,在其中我们正在添加列并在同一事务中更新列。

但是有一个问题。如果在批处理中发生错误,则脚本将继续下一个批处理,并编译并执行它。因此,如果在上一个批次中发生错误,我需要一种在下一次批处理中知道的方式。

要进行测试,请运行以下代码:

开始交易- 批量0.开始尝试改变雇员活性钻头;结束尝试开始抓住打印'错误号:'+str.error_number.;打印'电话号码: '+str.error_line.;打印错误信息;回滚交易;结束抓住;- 批量1开始尝试更新雇员活性=1;改变雇员改变活性钻头空值;结束尝试开始抓住打印'错误号:'+str.error_number.;打印'电话号码: '+str.error_line.;打印错误信息;回滚交易;结束抓住;承诺交易;

在上面的示例代码中,我在第一个批处理中抛出异常,但是让我们假设在这里有一些错误。这个代码的问题是那个仍处于第二批次当第一个批处理中发生错误时。此外,要提交交易的陈述也试图执行。因此,我们在SQL Server Management Studio中获得以下错误。

错误编号:50000行号:5我们正在提高故意测试的错误。MSG 208,第16级,第1级,第4行无效的对象名称“员工”。MSG 3902,级别16,状态1,第2行提交事务请求没有相应的开始事务。

解决方案是使用设置xact_abort命令。这使SQL Server在一个SQL语句中发生错误时重新回滚事务。使用此设置为ON,我们可以使用xact_state()确定我们交易状态的方法。

xact_state()返回以下整数值:

  • -1在我们的交易中发生错误时,
  • 0.当交易不存在或已退回时,并且
  • 1当事务处于活动状态时(没有发生错误)。

我们可以使用每个批处理中的Xact_state()测试事务状态的值。这是最终解决方案代码。

xact_abort.;开始交易- 批量0.开始尝试raiserror.“我们正在举起故意测试错误。”18.0.;改变雇员活性钻头;结束尝试开始抓住打印'错误号:'+str.error_number.;打印'电话号码: '+str.error_line.;打印错误信息;回滚交易;结束抓住;- 批量1开始尝试- 如果发生错误,则回滚事务如果Xact_State.=-1开始raiserror.'交易处于不可思议的状态。回滚交易。'18.3.;结束;- 如果交易回滚,请勿继续如果Xact_State.=0.开始raiserror.“交易回来了。”18.1;结束;- 将所有员工设置为活动更新雇员活性=1;- 不要允许活跃才能为null改变雇员改变活性钻头空值;结束尝试开始抓住打印'错误号:'+str.error_number.;打印'电话号码: '+str.error_line.;打印错误信息;如果Xact_State.<>0.开始打印'回滚交易......';回滚交易;结束;结束抓住;- 提交交易如果Xact_State.=1开始承诺交易;打印'交易承诺。';结束;

上述解决方案使用xact_state()在第二批处理中的方法,以确定我们在事务中是否有错误。这可确保我们可以具有单个事务,其中包含多个批处理,如果事务中的任何语句发生错误,则会回滚。

Brian F爱

嗨,我是布莱恩。我对类型名称,Angular和node.js感兴趣我嫁给了我最好的朋友邦妮,我住在波特兰和我滑雪(很多)。