【问题标题】:How to auto Shift primary keys to start from 1 again如何自动 Shift 主键再次从 1 开始
【发布时间】:2012-05-15 12:58:44
【问题描述】:

我正在使用如下创建的表:

CREATE TABLE [dbo].[Tag](
    [TagID] [int] IDENTITY(1,1) NOT NULL,
    [Value] [varchar](200) NOT NULL,
    [TagCount] [varchar](200) NULL,
 CONSTRAINT [PK_Tag] PRIMARY KEY CLUSTERED 
(
    [TagID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

我永远不能插入一个主键,它只是从最后一个自动继续。所以如果我最后一个条目的主键是 72,那么下一个条目就是 73。

现在我的问题是当我删除一个条目时。现在说我删除了条目的 3-7,我的数据库将存储条目的 1、2、8、9 等。

是否有一个存储过程可以在我删除后运行以仅自动转移我的主键再次从 1 排序?

【问题讨论】:

  • 你可以,但我不得不质疑“为什么?”
  • 它这样工作是有充分理由的,这样你就不会随着时间的推移给两个不同的东西提供相同的 ID。假设你有一个收据数据库,你不小心删除了一些收据,一个新客户进来,现在两个客户有一个 ID 相同的收据?!巫术。
  • 您正在寻找RESEED 索引。请参阅此处了解您将遇到的语法和问题:stackoverflow.com/a/4165362/1016183
  • “编程目的”——我们面前的喜剧演员。
  • @Pomster 我同意你的观点,它看起来不整洁,但它应该是这样的。没有两种方法。正确胜于整洁!

标签: sql sql-server database sql-server-2008 stored-procedures


【解决方案1】:

使用

TRUNCATE TABLE [dbo].[Tag]

这将清空所有数据并重置自动值计数器。

编辑: 如果要保存旧值。创建一个临时表,将所有数据存储在那里,截断您的主表并重新插入它们。但是你为什么要这样做呢?

类似这样的事情(在事务中执行):

CREATE TABLE [dbo].[TagTmp] (
 [Value] [varchar](200) NOT NULL,
    [TagCount] [varchar](200) NULL
)
INSERT INTO TagTmp (Value, TagCount)
SELECT Value, TagCount FROM dbo.Tag
TRUNCATE TABLE dbo.Tag
INSERT INTO Tag (Value, TagCount)
SELECT Value, TagCount FROM dbo.TagTmp
DROP TABLE TagTmp

EDIT2:

如果您想插入一条带有免费“旧”自动 ID 的记录,请使用:

SET IDENTITY_INSERT tablename OFF
INSERT INTO tablename (TagId, Value, tagCount) VALUES (3, 'value', 1');
SET IDENTITY_INSERT tablename ON

这会给你插入记录的机会,但我不建议这样做:)

【讨论】:

  • 但我不想丢失所有数据。我不能这样做并保留我的数据吗?
  • 每次我调用删除存储过程时,我都希望通过 C# 代码执行此操作。难道没有别的办法了吗?在我删除你的方法后,我需要它来自动拉屎,看起来像是一次修复。
  • @Pomster - 你总是想从 1 重新开始编号吗?即使你删除了记录#3,记录#1仍然存在?
  • 仍然不明白为什么要这样做。据我所知,除了您暂时关闭自动值并手动插入带有“旧自动 id'S”的新值(使用:SET IDENTITY_INSERT 表名 OFF/ON)之外,没有办法“修改”值。
  • @Pomster 正确,请勿触摸此 ID。为您自己的 porpuses 添加另一个 ID 列,如果需要,您可以使用更新功能来恢复您的行并按此列排序。
【解决方案2】:

简要说明您为什么不想这样做:

想象一下,如果每次有人取消他们的电话服务,电话公司就会返回并重新分配每个人的号码,并在取消的号码之上重新分配以消除差距。这将导致所有相关人员都感到头疼。

PK 不仅应该是唯一的,而且对于该行来说应该是恒定的。更改行的标识会导致问题。

如果您想在添加新记录时填补空白,您可以使用 IDENTITY INSERT,或从表中删除身份并在每次插入记录时生成自己的 id。

而且,如果由于某种原因您还没有进行沟通,您仍然想这样做 - RESEED 的答案是您的最佳选择。

【讨论】:

    【解决方案3】:

    你必须使用RESEED:

    DBCC CHECKIDENT (table_name, RESEED); 
    

    在删除后在触发器中使用它。

    【讨论】:

    • 这不是一个答案,因为他想全部使用,而不是重新设置最后一个值。
    • 在删除时检查被删除的记录数,获取索引值减去该值并使用此代码重置索引 DBCC CHECKIDENT(, RESEED, value)
    • 如果您只删除最后一条记录,这在理论上可能可行,但即使他的示例也表明他在添加了许多新记录后删除了旧行。
    • 哦,是的,我想我想念这个问题。不要更改现有记录的主键值,否则会出现数据问题。
    猜你喜欢
    • 2019-07-02
    • 2020-05-11
    • 1970-01-01
    • 2019-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-26
    相关资源
    最近更新 更多