如何在 SQL Server 中回滚或提交事务

Posted

技术标签:

【中文标题】如何在 SQL Server 中回滚或提交事务【英文标题】:How to rollback or commit a transaction in SQL Server 【发布时间】:2013-02-21 21:49:09 【问题描述】:

在我的存储过程中,我有三个插入语句。

在重复键值插入前两个查询产生错误

违反 PRIMARY KEY 约束

第三个查询照常运行。

现在我希望,如果任何查询产生任何异常,一切都应该回滚。

如果任何查询都没有产生任何异常,它应该被提交。

declare @QuantitySelected as char
    set @QuantitySelected = 2

    declare @sqlHeader as varchar(1000)
    declare @sqlTotals as varchar(1000)
    declare @sqlLine as varchar(1000)

    select @sqlHeader = 'Insert into tblKP_EstimateHeader '
    select @sqlHeader = @sqlHeader + '(CompanyID,CompanyName,ProjectName,EstimateID,EstimateHeader,QuoteDate,ValidUntil,RFQNum,Revision,Contact,Status,NumConfigurations) '
    select @sqlHeader = @sqlHeader + ' select CompanyID,CompanyName,ProjectName,EstimateID,EstimateHeader,QuoteDate,ValidUntil,RFQNum,Revision,Contact,Status,NumConfigurations '
    select @sqlHeader = @sqlHeader +  'from V_EW_Estimate_Header where EstimateID = 2203'



    select @sqlTotals = 'Insert into tblKP_Estimate_Configuration_Totals '
    select @sqlTotals = @sqlTotals + '(ConfigRecId,RecId,SellQty,ConfigNum,ConfigDesc,SortOrder,OptionsInMainPrice,MarkupPctQty,'
    select @sqlTotals = @sqlTotals + ' SellPriceQty,RubberStamp,OptPriceQty,StatusRecid,LastUpdate_Date,LastUpdate_User,TotalCost,QuantityBracketSelected)'
    select @sqlTotals = @sqlTotals + ' select ConfigRecId,RecId,SellQty' + @QuantitySelected + ',ConfigNum,ConfigDesc,SortOrder,OptionsInMainPrice'
    select @sqlTotals = @sqlTotals + ' ,MarkupPctQty' + @QuantitySelected + ',SellPriceQty' + @QuantitySelected + ',RubberStamp,OptPriceQty' + @QuantitySelected + ',StatusRecid,LastUpdate_Date,LastUpdate_User,TotalCost' + @QuantitySelected + ',' + @QuantitySelected
    select @sqlTotals = @sqlTotals + ' from v_EW_Estimate_Configuration_Totals where ConfigRecId = -3'


    select @sqlLine = 'Insert into tblKP_Estimate_Configuration_Lines'
    select @sqlLine = @sqlLine + '(MstrRfqRecId,RfqRecId,RfqLineRecId,CompanyId,VendorQuoteNum,LineGrp,LineNum,StatusRecId,'
    select @sqlLine = @sqlLine + ' LineDesc,LineSize,LineMatl,LineDeco,LineFinish,CopyFromRecId,PerPieceCost,IsOptional,'
    select @sqlLine = @sqlLine + ' CopyToNewRev,RecId,UnitPrice,LineQty,LinePrice,CustOrVend,SellQty1,RfqNum,ConfigLineIsOptional,ConfigLinePerPieceCost,ConfigLineRecid,SellPrice,SaleQty)'
    select @sqlLine = @sqlLine + ' select distinct MstrRfqRecId,RfqRecId,RfqLineRecId,CompanyId,VendorQuoteNum,LineGrp,LineNum,'
    select @sqlLine = @sqlLine + ' StatusRecId,LineDesc,LineSize,LineMatl,LineDeco,LineFinish,CopyFromRecId,PerPieceCost,IsOptional,'
    select @sqlLine = @sqlLine + ' CopyToNewRev,RecId,UnitPrice' + @QuantitySelected + ',LineQty' + @QuantitySelected + ', isnull(LinePrice' + @QuantitySelected + ', 0.0000),CustOrVend,SellQty' + @QuantitySelected + ',RfqNum,ConfigLineIsOptional,ConfigLinePerPieceCost,ConfigLineRecid,SellPrice' + @QuantitySelected + ',SaleQty' + @QuantitySelected
    select @sqlLine = @sqlLine + ' from v_EW_EstimateLine  where rfqlinerecid in (select RfqLineRecID from kp_tblVendorRfqConfigLine where ConfigRecID = -3) '

    exec( @sqlHeader)
    exec(@sqlTotals)
    exec(@sqlLine)

【问题讨论】:

欢迎使用 ***:如果您发布代码、XML 或数据示例,在文本编辑器中突出显示这些行并单击“代码示例”按钮 ( ) 在编辑器工具栏上很好地格式化和语法突出显示它! @marc_s 谢谢马克。我已经添加了我的 StoreProcedure。请检查一下。 这是一个存储过程 - 一个存储 在 SQL Server 中的 过程 - 它与“商店” .... 实际上我在这里根据某些条件将数据从一个表保存到另一个表。它是我的 StoreProcedure 的主要 scalaton 【参考方案1】:

好消息是 SQL Server 中的事务可以跨越多个批次(每个 exec 被视为一个单独的批次。)

您可以将 EXEC 语句包装在 BEGIN TRANSACTIONCOMMIT 中,但如果发生任何错误,您需要更进一步并回滚。

理想情况下你会想要这样的东西:

BEGIN TRY
    BEGIN TRANSACTION 
        exec( @sqlHeader)
        exec(@sqlTotals)
        exec(@sqlLine)
    COMMIT
END TRY
BEGIN CATCH

    IF @@TRANCOUNT > 0
        ROLLBACK
END CATCH

BEGIN TRANSACTIONCOMMIT相信你已经很熟悉了。 BEGIN TRYBEGIN CATCH 块基本上可以捕获和处理发生的任何错误。如果您的任何EXEC 语句引发错误,代码执行将跳转到CATCH 块。

您现有的 SQL 构建代码应该在事务之外(上图),因为您总是希望尽可能缩短事务。

【讨论】:

当我执行语句时。它工作正常。但在第一次工作时在 storeProcedure 中。在第二次执行 storeP 时,它会生成异常:-“EXECUTE 之后的事务计数表明 BEGIN 和 COMMIT 语句的数量不匹配。先前计数 = 0,当前计数 = 1。” 对不起,应该是IF @@TRANCOUNT > 0,我会更新我的答案。

以上是关于如何在 SQL Server 中回滚或提交事务的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SQL Server 2005 中回滚 UPDATE 查询?

如何在SQL Server 2005中回滚UPDATE查询?

Spring - 事务应该在一种方法中提交,但应该在执行数据库事务的其他方法中回滚

当其中一个引发错误时,如何从处理程序中回滚所有事务语句?

如何收缩 SQL Server 中的 Tempdb 数据库

sqlserver事务怎么开启 怎么提交 怎么回滚