我在SQL 2008服务器中有几个表,我需要为其生成唯一的ID。我查看了“身份”列,但ID确实需要是唯一的并且在所有表之间共享。
因此,如果我说(5)五个风格“资产基础设施”的表格,并且我想在它们之间使用唯一ID作为组合组运行,我需要某种生成器来查看所有(5)五表格并发出下一个ID,这些ID在任何(5)五个故事中都没有重复。
我知道这可以通过某种存储过程完成,但我不知道如何去做。有什么想法吗?
答案 0 :(得分:5)
最简单的解决方案是在每个表上设置您的身份种子和增量,以便它们永远不会重叠。 表1:种子1,增量5 表2:种子2,增量5 表3:种子3,增量5 表4:种子4,增量5 表5:种子5,增量5
标识列mod 5将告诉您记录所在的表。您将用尽您的标识空间五倍,因此请确保数据类型足够大。
答案 1 :(得分:4)
为什么不使用GUID?
答案 2 :(得分:4)
你可以让他们每个人都有一个身份,从远离足够数字的种子永远不会发生碰撞。
GUID会起作用,但它们很丑陋,而且非顺序,如果这很重要。
另一种常见技术是使用具有标识的单列表,每次插入记录时都会分配下一个值。如果你需要它们从一个共同的序列中拉出来,那么让第二列指示它被分配到哪个表面并不是没有用。
你意识到这有逻辑设计问题,对吗?
答案 3 :(得分:4)
稍微阅读一下设计,听起来你真正需要的是一个名为“Asset”的表,带有一个标识列,然后是:
a)资产子类型的5个附加表,每个表都有一个外键到资产的主键;或
b)资产的5个视图,每个视图都选择行的子集,然后显示(对用户),就像你现在拥有的5个原始表一样。
如果表上的列都相同,(b)是更好的选择;如果他们都不同,(a)是更好的选择。这是超类型/子类型关系的经典DB旋转。
或者,你可以做你正在谈论的事情并自己重新创建IDENTITY功能,并在所有5个表上包含INSERT访问权限的存储过程。请注意,如果要保证唯一性,则必须在其周围放置TRANSACTION,如果这是一个受欢迎的表,则可能会使其成为性能瓶颈。如果这不是一个问题,这样的过程可能采取以下形式:
CREATE PROCEDURE InsertAsset_Table1 (
BEGIN TRANSACTION
-- SELECT MIN INTEGER NOT ALREADY USED IN ANY OF THE FIVE TABLES
-- INSERT INTO Table1 WITH THAT ID
COMMIT TRANSACTION -- or roll back on error, etc.
)
同样,SQL经过高度优化,可以帮助您选择我上面提到的模式,而不是针对此类事情进行优化(创建事务会产生开销,并且您将在所有5个表上发布共享锁定这个过程正在进行中)。相比之下,使用上面的PK / FK方法,其中SQL Server确切地知道如何在没有锁的情况下执行它,或者将视图方法用于仅插入到1个表中。
答案 4 :(得分:0)
我在google上搜索时发现了这一点。我第一次面临类比问题。我有一个专门用于生成ID的专用ID表的想法,但我不确定它是否被认为是好的设计。所以我只想说感谢确认..看起来这是一个充分的解决方案虽然不理想。
答案 5 :(得分:0)
我有一个非常简单的解决方案。对于表格数量很少的情况应该是好的:
create table T1(ID int primary key identity(1,2), rownum varchar(64))
create table T2(ID int primary key identity(2,2), rownum varchar(64))
insert into T1(rownum) values('row 1')
insert into T1(rownum) values('row 2')
insert into T1(rownum) values('row 3')
insert into T2(rownum) values('row 1')
insert into T2(rownum) values('row 2')
insert into T2(rownum) values('row 3')
select * from T1
select * from T2
drop table T1
drop table T2
答案 6 :(得分:0)
这是一个常见的问题,例如,当使用人员表(请称为PERSON单数)并且每个人都被分类时,例如医生,患者,员工,护士等。
为每个人创建一个包含其特定类别信息的表格很有意义,例如员工开始日期和工资以及护士资格和编号。
例如,患者可能有许多护士和医生在他身上工作,因此在PERSON表中将患者与其他人联系起来的多对多表格可以很好地促进这一点。在这个表格中应该有一些关于这些人之间关系的描述,这些描述将我们带回到人们的类别。由于Doctor和Patient可以在自己的表中创建相同的主键ID,因此拥有全局唯一ID或对象ID变得非常有用。
按照建议执行此操作的一种好方法是将表指定为自动递增主键。首先在该表上执行插入以获取OID,然后将其用于新PERSON。
我想更进一步。当事情变得丑陋(一些新的开发人员得到了数据库,或者更糟糕的是,一个非常老的开发人员,那么为OID添加更多意义非常有用。
通常这是以编程方式完成的,而不是使用数据库引擎,但如果您对所有主键ID使用BIG INT,则您有足够的空间为具有可视识别序列的数字添加前缀。例如,所有医生ID都可以从100开始,所有患者都是110,所有患者都是120.
我要追加说Julian日期或Unix日期+时间,最后附加自动增量ID。
这会产生如下数字:
110,2455892,00000001
120,2455892,00000002
100,2455892,00000003
由于从现在起100年后的朱利安日期仅为2492087,您可以看到7位数字将足以存储该值。
BIGINT是64位(8字节)有符号整数,范围为-9.22x10 ^ 18到9.22x10 ^ 18(-2 ^ 63到2 ^ 63 -1)。请注意,指数是18.这是您必须使用的18位数。
使用这种设计,您可以限制在1亿个OID,999个类别的人和日期......远远超过数据库的保质期,但我怀疑这对于大多数解决方案来说已经足够了。
创建像这样的OID所需的操作都是乘法和除法,它避免了文本操作的所有齿轮磨削。
缺点是INSERT需要的不仅仅是一个简单的TSQL语句,但优点是当你追踪错误数据甚至在你的查询中聪明时,你的OID在视觉上告诉你不仅是一个随机数或更糟糕的,像GUID一样的眼睛。