SQL Server事务成功,Id错误



我有一个简单的SQL语句来创建这样的表:

Create table tblAccountBalance
(
    Id int,
    AccountName nvarchar(200),
    Balance int
)
insert into tblAccountBalance values (1, 'Mark', 1000);
insert into tblAccountBalance values (2, 'Mary', 1000);

导致

Id AccountName Balance
-----------------------
1  Mark        1000
2  Mary        1000

然后我创建一个这样的交易:

begin try
    begin transaction   -- must have transaction keyword here!
        update tblAccountBalance 
        set Balance = Balance - 100 
        where Id = 1
        update tblAccountBalance 
        set Balance = Balance + 100 
        where Id = 2
        commit transaction --or simply commit, but by default, it is commit WORK - thus you cannot specify transaction name, best is to put transaction
        print 'Transaction successful!'
end try
begin catch
    rollback transaction --or simply rollback, but again, it might be similar to transaction, best is to put transaction keyword
    print 'Transaction is rolled back!'
end catch

当执行时,只需将100个单位的钱从马克转移给玛丽:

Id AccountName Balance
-----------------------
1  Mark        900
2  Mary        1100

现在,从上面更新的表继续,为了在事务中引入错误,我更改事务,使第二个更新语句的Id为nvarchar,如下所示:

begin try
    begin transaction
        update tblAccountBalance 
        set Balance = Balance - 100 
        where Id = 1
        update tblAccountBalance 
        set Balance = Balance + 100 
        where Id = '24'    -- note the Id here is changed
        commit transaction
        print 'Transaction successful!'
end try
begin catch
    rollback transaction
    print 'Transaction is rolled back!'
end catch

令我惊讶的是,执行上面的查询结果是:

(1 row(s) affected)
(0 row(s) affected)
Transaction successful!
Id  AccountName Balance
-----------------------
1   Mark        800
2   Mary        1100

这不是想要的结果。

但是,如果我从上面不希望的更新表结果继续进行修改的事务(再次,在第二个更新Id中),如下所示:

begin try
    begin transaction
        update tblAccountBalance 
        set Balance = Balance - 100 
        where Id = 1
        update tblAccountBalance 
        set Balance = Balance + 100 
        where Id = 'A24'     -- note the Id here is changed
        commit transaction
        print 'Transaction successful!'
end try
begin catch
    rollback transaction
    print 'Transaction is rolled back!'
end catch

这导致:

(1 row(s) affected)
(0 row(s) affected)
Transaction is rolled back!
Id  AccountName Balance
------------------------
1   Mark        800
2   Mary        1100

这是我想要的结果。第二笔交易怎么了?为什么更新仍在执行?

如果这很重要的话,我正在使用SQL Server 2014。

这是因为您的第二个实验实际上是成功的并执行了。当存在比较两种不同数据类型的操作时,SQL Server将执行隐式转换。有关更多详细信息,请参阅数据类型优先级。所以id = '24'转换为int类型,所以它最终变成了id = 24。因此,实验将从Mark中扣除余额,并添加具有id = 24的记录的余额,但由于没有具有该id的记录,因此没有任何变化。

在第三个实验中,隐式转换失败(无法将A24转换为整数类型),最终事务被回滚。

您的第二个事务成功了,这就是为什么UPDATE仍然被执行的原因。您更改的UPDATE语句:

update tblAccountBalance set Balance = Balance + 100 where Id = '24' --note the Id here is changed

没有造成任何错误。它只是没有返回任何带有Id = '24'的行,但没有错误。

您的第三个事务导致了一个错误,这就是回滚UPDATE的原因。

update tblAccountBalance set Balance = Balance + 100 where Id = 'A24' --note the Id here is changed

以上将导致如下错误:

将varchar值"A24"转换为数据类型时转换失败内部

由于您的IdINT,SQL Server尝试将A24(即VARCHAR)转换为INT,但未能转换,因此出现错误。

您的第二个实验成功了,因为nvarchar可以隐式转换为int。字符串'24'可以转换为24的整数值。请参见隐式转换。

最新更新