我有一个简单的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
现在,从上面更新的表继续,为了在事务中引入错误,我更改事务以使第二个更新语句具有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.
答案 0 :(得分:3)
这是因为你的第二个实验实际上已成功并被执行。当存在比较2种不同数据类型的操作时,SQL Server将执行隐式转换。有关详细信息,请参阅Data Type Precedence。因此,您的id = '24'
转换为int类型,因此最终会变为id = 24
。因此,实验将从Mark中扣除余额,并使用id = 24
添加记录余额,但由于没有此ID的记录,因此没有任何变化。
在第三个实验中,隐式转换失败(无法将A24
转换为整数类型)并最终回滚事务。
答案 1 :(得分:1)
您的第二笔交易成功,这就是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'转换为数据类型时转换失败 中间体
由于您的Id
为INT
,SQL Server会尝试将A24
VARCHAR
转换为INT
,但无法执行此操作,从而导致错误。
答案 2 :(得分:1)
您的第二个实验成功,因为nvarchar
可以隐式转换为int
。字符串'24'
可以转换为24
的整数值。请参阅Implicit Conversions。