【发布时间】:2020-02-20 13:40:30
【问题描述】:
为什么这个ROLLBACK TRANSACTION 语句不起作用?
BEGIN TRANSACTION;
DECLARE @foo INT
EXECUTE [database].[dbo].[get_counter] @CounterID='inventory_records', @nextValue=@foo OUTPUT;
ROLLBACK TRANSACTION;
背景
我正在将记录插入到基于 SQL Server 19 构建的客户 ERP 系统中。ERP 数据库没有自动递增的主键。它改为使用一个名为counters 的表,其中每一行都有一个counterID 字段和一个整数value 字段。
要在inventory_record 这样的表中插入新行,我首先需要调用这样的存储过程:
EXECUTE get_counter @counterID='inventory_record'
此过程返回一个名为@nextValue 的OUT 参数,然后我将INSERT 作为其uid 放入inventory_record 表中。
如果我的插入失败,我需要ROLLBACK 这个存储过程的行为。这样,计数器不会在 INSERT 尝试失败时无限增加。
get_counter存储过程的内容
这很简单,但也受版权保护。我在这里进行了总结和截断。计数器作为序列存储在 DB 中。所以get_counter 在检查请求的计数器是否合法后调用sp_sequence_get_range。
ALTER PROCEDURE get_counter
@strCounterID varchar(64),
@iIncrementValue integer = 1,
@LastValue BIGINT = NULL OUTPUT
AS
SET NOCOUNT ON
BEGIN
DECLARE
@nextSeqVar SQL_VARIANT
, @lastSeqVar SQL_VARIANT
-- code that confirms valid counter name
BEGIN TRY
-- code that calls [sp_sequence_get_range]
END TRY
BEGIN CATCH
THROW
END CATCH
RETURN(@LastValue)
END
问题
inventory_record 计数器总是递增。我无法回滚。
如果我从 SSMS 运行此问题顶部的 SQL,然后是 SELECT value FROM counters WHERE counterID = 'inventory_record',则每次执行时计数器都会递增。
我是 SQL Server 中事务处理的新手。有什么我想念的想法吗?
【问题讨论】:
-
为什么不转换为 PK 的 IDENTITY 数据类型?
get_counter中有COMMIT吗? -
get_counter的代码是什么样的? -
@MartinSmith 我添加了有关 get_counter 的详细信息。基本上它只是调用一个从序列中获取下一个值的内置系统过程。这两个过程都没有使用任何
COMMIT语句。 -
@alexherm 因为这是一个客户端安装,上面有一个大型 C++ 应用程序,所以我无法更改数据在数据库中的存储方式。
-
您的
insert语句是否包含在与get_counter相同的BEGIN TRAN中?