我们有一个包含查询的大型数据库,每个enquirys都使用Guid引用。 Guid不是非常客户友好,所以我们想要额外的5位数“人类ID”(好吧,因为我们很可能在任何时候都不会有超过99999个激活,并且如果一个人类引用多个enrecys就可以了因为它们不用于任何重要的事情。)
1)在99999之后有没有办法让IDENTITY列重置为1?
我目前的解决方法是使用INT IDENTITY(1,1) NOT NULL
列,并在呈现HumanId时使用HumanId % 100000
。
2)有没有办法在[0..99999]上自动“随机分配”ID,以便两个相继创建的附件无法获得相邻的ID?我想我正在寻找一种双向的一对一哈希函数?
...理想情况下,我想在创建查询时使用T-SQL自动创建这些id来创建它。
答案 0 :(得分:3)
如果性能和并发性不是太大的问题,您可以使用触发器和MAX()函数来计算“下一个人类ID”值。您可能希望保留IDENTITY列,并在单独的列中包含“人员ID”。
编辑:在旁注中,这听起来像是一个“表示层”问题,不应该在您的数据库中。您的应用程序的表示层应该有代码担心以人类可读的方式呈现记录。只是一个想法...
答案 1 :(得分:2)
我强烈建议您重新审视自己的逻辑。你的方法有一些危险,包括:
重复使用ID总是一个坏主意,即使原始记录已经“过时” - 你是否因为继续增加ID超过99999而失去任何东西?这里的问题更可能是长期维护,特别是如果系统随时间发展的危险。另一件需要考虑的事情 - 用户是否有机会获取此参考编号,并在将来的某个阶段使用它来参考您的系统?
通过手动分配生成的/随机ID,您需要确保多个记录未分配相同的ID。您必须遵循一些选项(例如,使用事务),但是您应该确保事务的范围不会让您对并发事务被阻止的问题持开放态度 - 这可能会导致一些问题例如。性能。通过外部生成ID(因为SQL不能随机执行),然后在数据库上强制执行唯一约束(可能是按照Firoz Ansari建议的方式),可能最有效。
如果您仍想重置标识列,可以使用DBCC CHECKIDENT命令完成此操作。
可以在此处找到在SQL Server中生成随机种子的示例: http://weblogs.sqlteam.com/jeffs/archive/2004/11/22/2927.aspx
答案 2 :(得分:2)
如果您绝对需要在数据库中执行此操作,那么为什么不直接从GUID列派生您的人性化值?
-- human_id doesn't have to be calculated when you retrieve the data
-- you could create a computed column on the table itself if you prefer
SELECT (CAST(your_guid_column AS BINARY(3)) % 100000) AS human_id
FROM your_table
这将为您提供0到99999之间的随机值,该值来自GUID的前3个字节。如果您想要更大或更小的范围,请相应地调整除数。
答案 3 :(得分:1)
您可以创建具有两列的复合主键,例如..BatchId和HumanId。 这些列中的记录如下所示:
BatchId,HumanId
1,1
1,2
1,3
1,99998
1,99999
2,1
2,2
3,3
使用MAX或ORDER BY DESC获取具有BachId条件的下一个可用HumanId
SELECT TOP 1 @NextHumanId=HumanId
FROM [THAT_TABLE]
ORDER BY BatchId DESC, HumanID DESC
IF @NextHumanId>=99999 THEN SET @NextHumanId=1
希望得到这个帮助。
答案 4 :(得分:0)
您可以拥有一个可用的HUMANID表,每次添加查询时,您都可以从表中随机拉出一个HUMANID(并删除它),每次删除查询时都可以将其添加回来(通过INSERTing)。