基于行的计数器的行为可以像SEQUENCE或IDENTITY吗?

问题描述 投票:0回答:1

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。

注:由于事务回滚等导致的序列间隔不是问题,因为此类异常可以记录下来,因此可以自动记录。另外,事实发生后,偶尔的辍学情况可能会被调查,并记录是否以及何时伙伴要求致电顺序中出现差距的原因,只要这些差距非常小且相距甚远。

sql-server tsql sql-server-2014
1个回答
0
投票

正如Larnu和我都说过的,您可以很容易地在单个表上利用ROW_NUMBER。

我创建了一个Transfers表,并创建了一些示例数据来表示有2个合作伙伴。我正在使用sys.objects生成一些2018年和2019年的随机日期,如果您在这两年中都没有创建对象,则可能需要调整此日期,但似乎不太可能。这将为每个合作伙伴生成序号,并且每年重新启动。希望这将是一个很好的起点。

if OBJECT_ID('tempdb..#Transfers') is not null
    drop table #Transfers

create table #Transfers
(
    TransferID int identity
    , PartnerID int
    , TransferDate datetime
)

insert #Transfers
select top 5 1, create_date
from sys.objects
where create_date > '20180101' --to limit to only two years to demonstrate partitioning
order by NEWID()

insert #Transfers
select top 5 2, create_date
from sys.objects
where create_date > '20180101' --to limit to only two years to demonstrate partitioning
order by NEWID()

select *
    , MySeq = ROW_NUMBER()over(partition by PartnerID, datepart(year, TransferDate) order by TransferDate desc)
from #Transfers
© www.soinside.com 2019 - 2024. All rights reserved.