SQL Server中数据库范围内唯一而简单的标识符
首先,我知道这个问题 ,并且(使用GUID)的build议不适用于我的情况。
我想要简单的UID,以便我的用户可以通过电话轻松地交stream这些信息:
你好,1584号订单有问题
而不是
你好,我订单4daz33-d4gerz384867-8234878-14有一个问题
我想要那些是唯一的(数据库范围),因为我有几种不同的'对象'…有订单ID,交货ID和帐单ID,并且因为这些关系之间没有一对一的关系,我没有办法猜测ID是指什么types的对象。
借助数据库范围内唯一的ID,我可以立即知道客户所指的是什么对象。 我的用户只需在search工具中input一个ID,我就可以省去额外的点击,进一步完善正在查找的内容。
我目前的想法是使用具有不同种子1,2,3等的标识列,并且增量值为100。
这提出了一些问题,但:
-
如果我最终得到超过100个对象types呢? 授予我可以使用1000或10000,但不能很好地“扩散”
-
种子是否有可能“丢失”(在复制期间,数据库问题等)?
-
更普遍的是,还有其他问题我应该知道吗?
-
是否有可能使用一个非整数(我当前使用bigints)作为标识列,以便我可以用表示对象types的东西的ID前缀? (例如一个varchar列)
-
使用一个只包含一个标识列的“主表”,也许是一个对象types,这样在每当需要一个新的想法时,我就可以在其中插入一行。 我觉得这可能有点矫枉过正,恐怕会让我所有的插入请求变得复杂。 再加上我不能在不查看数据库的情况下确定对象types
-
还有其他巧妙的方法来解决我的问题?
为什么不在所有的桌子上使用身份,但是每当你把它展示给用户的时候,只需要使用一个字符就可以了。 例如O1234是订单,D123213是交货等? 这样你就不必制定一些疯狂的计划
在用户界面处理 – 在向用户报告ID号码时在其上添加前缀字母(或字母)。 所以o472将是一个命令,b531将是一个账单,依此类推。 人们在给电话“数字”的时候很容易混合字母和数字,而且比直接数字更准确。
您可以使用自动增量列来生成唯一的ID。 然后有一个计算列,它取这个列的值,并用一个反映实体types的固定标识符(例如OR1542和DL1542)分别表示订单#1542和订单#1542。 您的前缀可以根据需要进行扩展,可以安排格式来帮助在具有相同自动增量值的项目(例如OR011542和DL021542)之间进行区分,前缀为OR01和DL02。
我将通过定义一个通用的根表来实现。 缺乏一个更好的名字称之为实体。 实体表应该至less有一个标识列。 你也可以包含所有对象中常见的其他字段,甚至包含元数据,告诉你这一行是一个例子。
您的每个实际订单,交货…表都将具有返回到实体表的FK参考。 这会给你一个唯一的ID列
在我看来,使用种子是一个坏主意,可能会导致问题。
编辑
你提到的一些问题已经提到。 我也看到这是一个痛苦跟踪,并确保您正确设置所有新的实体。 想象一下开发人员从现在开始两年更新系统。
在我写了这个答案之后,我想到了更多关于你为什么这么做的问题,而且我也得出了和马特一样的结论。
MS的有意编程项目有一个GUID到字的系统,从随机ID给出可读的名字
为什么不用一个简单的Basel表示bigint? http://en.wikipedia.org/wiki/Base_36
我们在一个项目上面临类似的问题。 我们通过首先创build一个只有一行的简单表来解决它:一个BIGINT被设置为自动增量标识。 而且我们创build了一个在该表中插入新行的sproc,使用默认值并在事务中。 然后将SCOPE_IDENTITY
存储在variables中,回滚事务,然后返回存储的SCOPE_IDENTITY
。
这给了我们在数据库里面一个唯一的ID而不填满一张表。
如果你想知道ID是指什么types的对象,我会丢失事务回滚,并沿着ID存储对象的types。 这样找出Id是指什么types的对象是只有一个select(或内部连接)了。
我使用这个高/低的algorithm。 虽然我找不到这个在线说明。 必须在这里博客。
在我的数据库中,我有一个带有计数器字段的ID表。 这是最重要的部分。 在我的申请中,我有一个从0到99的计数器。这是低的部分。 生成的密钥是100 *高+低。
为了得到一个关键,我做了以下
initially high = -1 initially low = 0 method GetNewKey() begin if high = -1 then high = GetNewHighFromDatabase newkey = 100 * high + low. Inc low If low = 100 then low = 0 high = -1 return newKey end
真正的代码是更复杂的锁等,但这是一般的要点。
有很多方法可以从数据库中获得高价值,包括自动encryption键,生成器等。最好的方法取决于你使用的数据库。
这个algorithm给出了简单的键,同时避免了每次查找新键的db命中。 在testing中,我发现它的性能与GUID相似,而且性能也比每次检索一个auto inc的密钥要好得多。
您可以使用您的标识和子types字段创build一个主UniqueObject
表。 子表(订单,用户等)将有一个FK到UniqueObject。 INSTEAD OF INSERT
触发器应该把疼痛降到最低。
也许一个itemType-year-week-orderNumberThisWeek变种?
o2009-22-93402
这样的标识符可以由多个数据库列值组成,并由软件简单地格式化成标识符的forms。
我和一个项目有类似的情况。
我的解决scheme:默认情况下, 用户只能看到GUID的前7个字符。
这是非常随机的,碰撞是非常不可能的(1亿2千6百万),这是有效的说话和打字。
在内部,当然,我正在使用整个GUID。