【问题标题】:Replace MSSQL auto increment identity with a regular sequence用常规序列替换 MSSQL 自动增量标识
【发布时间】:2020-02-24 13:09:35
【问题描述】:

MSSQL Server 的自动增量标识列无法按预期工作,这对我来说是个突如其来的麻烦。

它不能保证一致的顺序。我的意思是,如果它像1, 2, 3, 4, 5 一样,以防你重新启动服务器,它可以像10006, 10007, 10008, 10009, 10010 一样轻松地继续。如果您有一些使用这些数字生成的文档(比如说合同),则可能会导致您的公司与数字 1, 2, 3, 4, 5 签订合同,然后意外更改为 10006, 10007, 10008, 10009, 10010

在其他 RDBM 上,自动增量列始终保持一致性,您是否重新启动它并不重要。

所以现在我想将该列更改为由序列提供服务。问题是我怎样才能最大限度地顺利完成?我使用实体框架及其迁移机制。

列定义为:

CREATE TABLE [dbo].[
    -- omitted for the sake of brevity
    [CompanyNo] [bigint] IDENTITY(1,1) NOT NULL
    -- omitted for the sake of brevity
);

我最好的猜测是创建一个迁移:

  1. 获取列CompanyNo的当前最新值
  2. 修改列使其不自动递增
  3. 使用第 1 步的起始值创建序列

技术:

  • 实体框架 6 + 迁移 + 代码优先
  • MSSQL
  • ASP.NET MVC

【问题讨论】:

  • 请记住,序列也不能保证是无间隙的,除非您使用 NO CACHE 创建它们,这会强制 SQL Server 使用事务来提交每个增量——正是身份的更改以提高性能。强烈考虑更改流程的其余部分,这样它就不需要依赖完美无间隙的序列,而是满足于唯一性——抛开性能不谈,这大大提高了鲁棒性(请注意,连续序列可能会无意中暴露敏感信息,例如您每天关闭多少合约)。
  • 请注意,您的流程中的第 2 步“修改列以使其不自动递增”在 SQL Server 中是不可能的——列的 IDENTITY 属性在表已创建。如果您不想重新创建数据库,则必须创建一个新表并传输旧数据。这可以通过ALTER TABLE SWITCH 轻松完成,但我怀疑 EF 是否可以自动执行类似的操作;您需要手动迁移步骤。

标签: sql-server entity-framework sequence entity-framework-migrations auto-increment


【解决方案1】:

我的建议是在您的表中添加一个时间戳列,该列在添加给定记录时进行逻辑记录。然后,当您想要生成序列时,您可以使用ROW_NUMBER 即时生成:

SELECT *, ROW_NUMBER() OVER (ORDER BY ts_col) seq
FROM yourTable;

如果您需要有保证的有序序列,则不应依赖自动递增列,因为它不是为此而设计的。自增列的约定表明生成的值将始终是唯一的,并且通常会增加,但不一定是连续序列。

【讨论】:

  • 这是解决问题某一方面的一种方法,但值得注意的是,只有在没有删除任何行(或追溯插入)时,这才会保持一致的数字。如果有,行会突然改变它们的编号,这可能比避免新行的间隙更不理想。
猜你喜欢
  • 2018-07-30
  • 1970-01-01
  • 1970-01-01
  • 2012-06-06
  • 2022-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-16
相关资源
最近更新 更多