在两个表之间共享自动递增的主键

时间:2008-10-03 15:25:48

标签: sql sql-server

您好我想让两个表都有一个INT“id”列,它会自动递增但我不希望任何“id”列共享相同的数字。这叫做什么,最好的方法是什么?序列?迭代器?指数?增量器?

动机:我们正在从一个模式迁移到另一个模式,并且有一个网页可以读取这两个表并显示(int)ID,但是我不能为这两个表使用相同的ID。

我正在使用SQL Server 9.0.3068。

谢谢!

9 个答案:

答案 0 :(得分:14)

只需将身份增量配置为> 1,例如表1使用IDENTITY(1,10)[1,11,21 ...],表2使用IDENTITY(2,10)[2,12,22 ...]。如果以后需要,这也会为您提供一些扩展空间。

答案 1 :(得分:3)

如果我理解正确的话,我认为使用GUID将是最直接的方法。

SELECT NEWID()

答案 2 :(得分:2)

使用具有GUID(全局唯一标识符)类型的列。它是16字节,每行总是唯一的。

请注意,与普通整数键相比,您将获得显着的性能提升。

答案 3 :(得分:1)

使用另一个ID类型为int的表,默认为1,称为KeyID或其他。

让存储过程检索值,添加1,然后更新KeyID,然后将其返回到存储过程,该过程正在更新需要新唯一密钥的两个表。

这将确保ID是一个i​​nt,并且它在使用存储过程生成新ID的表集之间是唯一的。

答案 4 :(得分:1)

您可以在第三个表中定义IDENTITY列,使用它来生成ID值,但是您始终回滚您在表中所做的任何插入(以避免使其增长)。回滚事务不会回滚生成ID的事实。

我不是Microsoft SQL Server的常规用户,所以请原谅任何语法失误。但是我想到的是以下内容:

CREATE TABLE AlwaysRollback (
  id IDENTITY(1,1)
);

BEGIN TRANSACTION;
INSERT INTO AllwaysRollBack () VALUES ();
ROLLBACK TRANSACTION;

INSERT INTO RealTable1 (id, ...) VALUES (SCOPE_IDENTITY(), ...);

BEGIN TRANSACTION;
INSERT INTO AllwaysRollBack () VALUES ();
ROLLBACK TRANSACTION;

INSERT INTO RealTable2 (id, ...) VALUES (SCOPE_IDENTITY(), ...);

答案 5 :(得分:0)

我不知道你会怎么称呼它。

如果您不想使用GUID或单独的表,您还可以创建一个函数,该函数查看两个表中的id的最大值,并将一个值添加到该值(或类似的值)。

然后,您可以在两个表的插入触发器中调用该函数。

答案 6 :(得分:0)

我个人是GUID解决方案的粉丝,但这是一个可行的选择。

此问题的许多解决方案都避免使用GUID并使用了良好的旧整数。这在合并复制情况下也很常见,其中许多卫星站点与主站点合并,并且需要避免密钥冲突。

如果GUID不适合你,并且你绝对必须有int,bigint等,你可以随时使用IDENTITY列并让每个表具有不同的SEED值。这些数据类型的范围非常广泛,将范围拆分为可用的段并不太难,特别是如果你想要的只是两个分割。例如,基本int的范围从-2 ^ 31(-2,147,483,648)到2 ^ 31-1(2,147,483,647)。例如,这对于客户表就足够了。

Transact-SQL参考(SQL Server 2000) int, bigint, smallint, and tinyint

示例:

--Create table with a seed of 1 billion and an increment of 1
CREATE TABLE myTable
(
primaryKey int IDENTITY (1000000000, 1),
columnOne varchar(10) NOT NULL
)

答案 7 :(得分:0)

如果你真的需要用int来做这个并且你有一个自动递增的数字,我以前这样做的方法是将id字段自动递增函数更改为另一个表的序列。我不太确定ms sql或我的sql但是在pgsql中这意味着在sql中你会有这个字段

 id integer NOT NULL DEFAULT nextval('table_two_seq'::regclass),

其中table_two_sequence是另一个表的序列函数。然后通过插入一些数据来测试它。我真的很抱歉,如果这不会在ms sql中工作我试图避开它tbh。失败的GUID是其他人提到的最佳方式。或者当你在你使用的代码中插入时,你可以在其中放入一个算法,但它可能会变得混乱。

或者,考虑将数据放在一个表中,因为这可能是一种解决方法。如果你需要,你可以有一个模拟两个表的视图。只是一个想法。

希望我帮助过

答案 8 :(得分:0)

从SQL Server 2012开始,您可以声明一个序列对象 https://msdn.microsoft.com/en-us/library/ff878091.aspx这正是您所需要的。

使用表来模拟序列对象应该是非常简单的 以原子方式包含下一个序列值和存储过程 选择值和增量。 [你喜欢使用功能,但功能 不能有副作用。]

这个黑客怎么样?创建一个包含两列的表(MySequence):和Identity列(SequenceValue)和一个虚拟列(DummyValue),并使用此存储过程获取新的序列值。表中唯一的行将是检索到的最后一个序列值。

CREATE PROCEDURE GetNextValue 
AS
BEGIN
    DECLARE @value int = null;

    -- Insert statements for procedure here
    INSERT into MySequence (DummyValue) Values (null);

    SET @value = SCOPE_IDENTITY();

    DELETE from MySequence where SequenceValue <> @value

    SELECT @value as Sequence

    return @value
END

要使用序列,您必须管理目标表的插入 - 触发器可能会起作用。