【问题标题】:Replace primary key Identity with sequence starting with next AUTO_INCREMENT value用从下一个 AUTO_INCREMENT 值开始的序列替换主键标识
【发布时间】:2016-11-25 15:08:34
【问题描述】:

我目前有一张桌子,MessagesID 列是主键,使用标识填充。

x-----------------------------x
|    ID       |  Contents     | 
x-------------|---------------x
|    1        |  01234        |
|    2        |  56789        |
x-----------------------------x

我想删除ID 列上的标识,并通过从序列Messages_ID_Sequence 中填充ID 的默认值来替换它。

这在 SSDT 中很容易实现。但是,当我部署数据库项目时,Messages_ID_Sequence 中的第一个值是 1。当我查看为Messages_ID_Sequence 生成的 SQL 时,很明显为什么:

CREATE SEQUENCE [dbo].[CommandMsgs_MSGID_Sequence]
    AS BIGINT
    START WITH 1
    INCREMENT BY 1
    NO MAXVALUE
    NO CYCLE
    CACHE 10

当我尝试插入新的消息记录时会出现问题。序列中的第一个值 1 填充新记录的 ID 列并导致违反主键约束。

那么我如何确保在创建Messages_ID_Sequence 时,它会从身份提供的下一个ID 开始? Messages_ID_Sequence 的创建脚本上的 Build Action 必须设置为 Build,这样解决方案就不能涉及 SSDT 不理解的任何内容。

【问题讨论】:

    标签: sql-server sql-server-2012 sql-server-data-tools


    【解决方案1】:

    您可以动态地构造 SQL 语句来创建您的序列,因此它从您的最后一个身份开始。

    /* Read the last identity value */
    DECLARE @value bigint;
    select @value = max(id_field) from my_table;
    
    /* Create the sequence starting at that value */
    DECLARE @sql nvarchar(max);
    SET @sql = N'CREATE SEQUENCE [dbo].[CommandMsgs_MSGID_Sequence] AS BIGINT START WITH ' + cast(@value as nvarchar(20)) + ' INCREMENT BY 1 NO MAXVALUE NO CYCLE CACHE 10;';
    EXEC SP_EXECUTESQL @sql;
    

    或随时更新您的序列,使其从所需的值开始。

    /* Read the last identity value */
    DECLARE @value bigint;
    select @value = max(id_field) from my_table;
    
    /* Create the sequence starting at that value */
    DECLARE @sql nvarchar(max);
    SET @sql = N'ALTER SEQUENCE StreamEntrySequence RESTART WITH ' + cast(@value as nvarchar(20)) + ';';
    EXEC SP_EXECUTESQL @sql;
    

    【讨论】:

    • 我什么时候执行这个?作为部署后脚本?如果它被添加到我的部署后脚本中,它将在我每次发布数据库时执行。看起来这不一定有害,但考虑到每个环境只需要执行一次,这很浪费。
    • 您可以在您的部署脚本上执行它,就在创建序列之后。
    • 我已经更新了答案,所以现在它直接创建了序列,所以你只需要在更新数据库时调用它一次。
    • 序列由 SSDT 生成,我发布的创建脚本将 Build Action 设置为 Build。我无法用您回答中的脚本替换创建脚本,因为它会导致以下错误:SQL70001:此语句在此上下文中无法识别。
    • 好的,谢谢。我将把这个问题留几天,看看是否有人提出了我们没有想到的任何问题。如果没有,我会将其标记为已接受的答案。
    猜你喜欢
    • 1970-01-01
    • 2019-10-07
    • 2013-11-17
    • 2018-11-16
    • 2017-09-24
    • 1970-01-01
    • 2016-11-04
    • 2016-01-11
    • 2013-08-13
    相关资源
    最近更新 更多