运行UDATE语句

时间:2017-12-05 00:37:47

标签: sql-server tsql sql-server-2012 sql-update

运行更新语句时出错。 对于一个记录,它工作正常,但对于一大块记录,它给了我一个错误。

另外,为什么它告诉我64801行受影响然后1行受影响然后0?我该如何解释?

这是剧本:

update tblQuotes
set QuoteStatusID = 11, --Not Taken Up
    QuoteStatusReasonID = 9 --"Not Competitive"
where CAST(EffectiveDate as DATE) < CAST('2013-11-27' as DATE)
and CompanyLocationGuid = '32828BB4-E1FA-489F-9764-75D8AF7A78F1' -- Plaza Insurance Company
and LineGUID = '623AA353-9DFE-4463-97D7-0FD398400B6D' --Commercial Auto

enter image description here

我添加了BEGIN TRANSACTION声明,但它仍然无法正常工作。

BEGIN TRANSACTION
update tblQuotes
set QuoteStatusID = 11, --Not Taken Up
    QuoteStatusReasonID = 9 --"Not Competitive"
where CAST(EffectiveDate as DATE) < CAST('2017-11-27' as DATE)
 AND CompanyLocationGuid = '32828BB4-E1FA-489F-9764-75D8AF7A78F1' -- Plaza Insurance Company
and LineGUID = '623AA353-9DFE-4463-97D7-0FD398400B6D' --Commercial Auto
IF @@TRANCOUNT>0
COMMIT TRANSACTION

3 个答案:

答案 0 :(得分:2)

在我看来,这是一个“缺陷”,如果不是SQL Server中的“bug”。当您执行COMMIT事务时,TRANCOUNT减1.当您ROLLBACK任何事务时,调用堆栈中的所有事务都将回滚!这意味着任何尝试提交或回滚的调用过程都会出现此错误,并且您已经失去了调用堆栈的完整性。

在构建机制时,我在SQL Server上进行单元测试。我总是使用命名事务来解决它,如下例所示。你显然也可以查看XACT_STATE。关键在于,如果您按名称或事务ID管理事务,则可以更好地控制,而不是盲目地提交和回滚匿名事务。

对于单元测试,我将存储过程编写为调用测试过程的测试。单元测试处于可序列化或快照模式,并且仅包含回滚语句。我调用测试中的过程,验证结果,构建测试输出(通过/失败,参数等)作为XML输出,然后一切都回滚。这避免了构建“模拟数据”的需要。我可以在任何环境中使用数据,因为事务总是回滚。

--
-- get @procedure from object_name(@@procid)
-------------------------------------------------
DECLARE @procedure        SYSNAME = N'a_procedure_name_is_a_synonym_so_can_be_longer_than_a_transaction_name'
        , @transaction_id BIGINT;
DECLARE @transaction_name NVARCHAR(32) = RIGHT(@procedure + N'_tx', 32);

--
BEGIN TRANSACTION @transaction_name;

BEGIN
    SELECT @transaction_id = [transaction_id]
    FROM   [sys].[dm_tran_active_transactions]
    WHERE  [name] = @transaction_name;

    SELECT *
    FROM   [sys].[dm_tran_active_transactions]
    WHERE  [name] = @transaction_name;

-- Perform work here 
END;

IF EXISTS
   (SELECT *
    FROM   [sys].[dm_tran_active_transactions]
    WHERE  [name] = @transaction_name)
    ROLLBACK TRANSACTION @transaction_name; 

答案 1 :(得分:1)

此错误表明在SQL Server中,您已指定Commit或Commit Transaction而未指定Begin Transaction,或者提交事务的数量大于begin transaction的数量。为避免这种情况,请确保在提交之前检查当前会话中的现有事务。

因此,正常的提交交易将更新如下

IF @@TRANCOUNT>0
COMMIT TRANSACTION

答案 2 :(得分:0)

有一个触发器,可确保QuoteStatusID的完整性。因此,我的WHERE子句我必须准确指定当前状态ID策略必须具有哪些才能进行更新。