【发布时间】:2020-03-30 11:37:11
【问题描述】:
SEQUENCE 和 IDENTITY 为所有会话和事务提供全局唯一的递增值,无论隔离级别如何,它们不受事务回滚的影响。是否可以使用基于行的计数器获得相同的行为,如果可以,如何实现?
最大的问题似乎是在任何可能打开的事务范围之外执行计数器更新。服务器能否链接自己以一种“远程模式”调用自己的过程,这种模式可以穿透任何当前活动的事务和隔离模式?
“远程”调用可以调用一个简单的过程,像这样在自动提交模式下运行:
create or alter procedure dbo.next_value (@id int, @result int = null output)
as
begin
set nocount on;
update dbo.RowBasedCounters
set @result = counter_value = counter_value + 1
where counter_id = @id;
return @result;
end;
背景:我们需要与 SEQUENCE 或 IDENTITY 完全相同的行为作为外部通信伙伴的文件/传输计数器,每个伙伴需要三个独立的计数器。但是,使用 SEQUENCE 或 IDENTITY 并不真正可行,因为它们需要为每个计数器单独命名数据库对象(即它们是单例且没有键控),并且在任何情况下都有数千个伙伴,因此有数千个计数器。
P.S.:这些计数器编号传输(EDI 文件)和德国医疗保健系统中通信伙伴之间的传输尝试;每对合作伙伴的文件编号从每年 1 开始,传输尝试的编号以 1000 为模数,每对合作伙伴也是如此。 编号必须是连续的。编号方案由标准定义,不在我们的控制范围内。
我们使用的是 MS SQL Server 2014。
注意:由于事务回滚等导致的序列间隙不是问题,因为此类异常可以记录并因此自动记录。此外,可以在事后调查偶尔的辍学,并记录合作伙伴是否以及何时打电话询问序列中出现空缺的原因,只要这些空缺非常少且相距甚远。
【问题讨论】:
-
这里实际使用的计数器是什么;不是用
ROW_NUMBER来代替吗? -
真的没有办法按照你提议的方式处理这个问题。但这并不意味着没有一些可行的选择。每个合作伙伴的每个计数器都必须是唯一的,有什么理由吗?在我看来,身份应该适合您,除非您确实需要允许合作伙伴之间重复数字,否则您可以使用单个表格或序列来执行此操作。如果您还存储了 PartnerID,您甚至可以这样做。然后您可以使用 ROW_NUMBER 来获取顺序值。有很多方法可以处理这种情况。
-
如果您将其用于更新,上述内容可能很容易受到竞争条件的影响。
RETURN也用于说明 SP 的成功,而不是用于返回数据。0表示成功,其他都表示失败。你应该在这里使用OUTPUTparameter。 -
@Larnu:这些计数器编号传输(EDI 文件)和德国医疗保健系统中通信伙伴之间的传输尝试;每对合作伙伴的文件编号从每年 1 开始,传输尝试的编号以 1000 为模数,每对合作伙伴也是如此。编号方案由标准定义,不在我们的控制范围内。
-
这对我来说意义不大;我对德国医疗保健系统一无所知。但这并没有对我说“不,我们不能使用
ROW_NUMBER。”,正如我自己和@SeanLange 所建议的那样。
标签: sql-server tsql sql-server-2014