Sql server 2008 标识列的替代项
我们有一个带有标识列(OrderID)的Orders表,但我们的订单号由OrderType(2个字符)、OrderYear(2个字符)和OrderID(6个字符)组成,总共10个字符(即XX12123456)。 此计数器有限制:我们可以将标识999999作为OrderID。下一个订单的ID由7个字符组成。显然,我们不能保存重复的订单ID 因此,我们创建了一个以渐进式OrderID和OrderYear(例如,从100000到9999999,订单年从12到16)为前缀的表:此存储过程以可序列化隔离级别开始事务处理,获取未使用的第一个订单id,按使用情况更新并提交事务 作为Orders表,我担心在执行OrderID计算存储过程或重复的OrderID时会出现死锁 我将使用一个控制台应用程序来测试这一点,该应用程序创建多个并发线程,并尝试提取模拟生产负载的OrderID 疑问是:Sql server 2008 标识列的替代项,sql-server-2008,identity-column,Sql Server 2008,Identity Column,我们有一个带有标识列(OrderID)的Orders表,但我们的订单号由OrderType(2个字符)、OrderYear(2个字符)和OrderID(6个字符)组成,总共10个字符(即XX12123456)。 此计数器有限制:我们可以将标识999999作为OrderID。下一个订单的ID由7个字符组成。显然,我们不能保存重复的订单ID 因此,我们创建了一个以渐进式OrderID和OrderYear(例如,从100000到9999999,订单年从12到16)为前缀的表:此存储过程以可序列化隔离级
- 是否存在另一种安全模拟标识列的方法
- 其他想法D
BEGIN TRANSACTION OrderID
SELECT TOP 1 @AnnoOrdine = AnnoOrdine, @IdOrdine = IdOrdine
FROM ORDINI_PROGRESSIVI --WITH (ROWLOCK)
WHERE Attivo = 1
--ORDER BY AnnoOrdine ASC, IDOrdine ASC
UPDATE ORDINI_PROGRESSIVI WITH (UPDLOCK)
SET Attivo = 0
WHERE AnnoOrdine = @AnnoOrdine AND IdOrdine = @IdOrdine
IF ISNULL(@IdOrdine, '') = '' OR ISNULL(@AnnoOrdine,'') = ''
BEGIN
RAISERROR('Deadlock', 1, 1205)
END
SET @retry = 0
COMMIT TRANSACTION OrderID
SELECT @AnnoOrdine AS AnnoOrdine, @IdOrdine AS IdOrdine
END TRY
BEGIN CATCH
IF (ERROR_NUMBER() = 1205)
SET @retry = @retry - 1;
ELSE
SET @retry = -1;
IF XACT_STATE() <> 0
ROLLBACK TRANSACTION;
END CATCH
begintransactionorderid
选择顶部1@AnnoOrdine=AnnoOrdine,@IdOrdine=IdOrdine
来自ORDINI_PROGRESSIVI——与(ROWLOCK)
其中,Attivo=1
--安诺丁ASC订购,伊诺丁ASC订购
使用(UPDLOCK)更新ORDINI_PROGRESSIVI
设置为0
其中AnnoOrdine=@AnnoOrdine和IdOrdine=@IdOrdine
如果ISNULL(@IdOrdine,“)=”或ISNULL(@AnnoOrdine,“)=”
开始
RAISERROR('死锁',11205)
结束
设置@retry=0
提交事务医嘱ID
选择@AnnoOrdine作为AnnoOrdine,选择@IdOrdine作为IdOrdine
结束尝试
开始捕捉
如果(错误号()=1205)
设置@retry=@retry-1;
其他的
设置@retry=-1;
如果XACT_STATE()0
回滚事务;
端接
结束
这种方法减少了死锁(根本不存在),但有时输出参数为空。
使用30个当代线程进行测试(因此,30个客户进程同时插入订单)
这里是一个带有查询持续时间的调试日志,以毫秒为单位:
对于生产来说足够健壮吗?如果您确实发现当前解决方案正在产生问题,并且可能不会,那么另一种方法是为要创建的每个id类型创建一个表,其中包含一个标识列和一个虚拟字段 即: 然后可以将一条记录插入该表,并使用内置函数检索标识 即 您可以在需要时从这些表中删除,并在年底重新设置id计数器
您甚至可以在回滚的事务中包装插入-标识值不受回滚的影响是订单类型与订单ID分开的-即:您可以拥有AA120123456和AB120123456吗?是,我们希望按订单类型使用不同的id SQL Server 2012具有
序列
对象,允许您定义数字序列,完全独立于任何表。您可以为所需的每种订单类型设置一个序列,然后在插入行之前检索这些值。Ops!我不注意“2012”(你有粗体字:D)我们使用2008。更倾向于避免手动重置身份。我将尝试序列方法,我可以设置最小值和最大值,内置缓存功能和自动循环。太完美了@ShArDiCk如果您有SQL 2012,它是:)
ABtypeID (ABID int identity(1,1), dummy varchar(1))
insert ABTypeID (dummy) values (null)
select Scope_Identity()