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

Posted

技术标签:

【中文标题】在两个表之间共享自增主键【英文标题】:Share auto-incremented primary key between two tables 【发布时间】:2008-10-03 15:25:48 【问题描述】:

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

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

我使用的是 SQL Server 9.0.3068。

谢谢!

【问题讨论】:

您能补充一下为什么需要这样做吗?可能会有更好的设计不需要使用 GUID。 【参考方案1】:

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

【讨论】:

我该怎么做?有没有办法使用 phpMyadmin 做到这一点? 同时考虑使用 bigint。 请注意,使用SET IDENTITY_INSERT 可以插入一个不会作为自动编号发出的值。您可以通过检查约束来防止这种情况:alter table foo add check (Id % 10 = 0).【参考方案2】:

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

SELECT NEWID()

【讨论】:

对不起,我应该提到它需要是一个 int。【参考方案3】:

使用具有 GUID(全局唯一标识符)类型的列。它是 16 字节,并且对于每一行将始终是唯一的。

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

【讨论】:

【参考方案4】:

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

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

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

【讨论】:

【参考方案5】:

您可以在第三个表中定义一个 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(), ...);

【讨论】:

【参考方案6】:

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

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

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

【讨论】:

【参考方案7】:

我个人是 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
)

【讨论】:

【参考方案8】:

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

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

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

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

希望我有帮助

【讨论】:

【参考方案9】:

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

用表格模拟序列对象应该很简单 以原子方式包含下一个序列值和存储过程 选择值和增量。 [你想使用函数,但是函数 不会有副作用。]

这个黑客怎么样?创建一个包含两列的表 (MySequence):以及标识列 (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

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

【讨论】:

以上是关于在两个表之间共享自增主键的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 2000中如何设置自增主键?

mybatis怎么设置主键自增

mysql的设置主键自增的问题

MySQL手动插入数据时怎么让主键自增!

SQ数据库中怎样设置自增主键?

mysql如何设置自增主键