身份规范

时间:2019-05-15 07:54:50

标签: sql sql-server identity

在SQL Server 2016中创建表时,身份规范存在问题。

  • 在ID列中,我将身份增量和身份种子设置为1。
  • 接下来,我将新记录添加到新表中。
  • 在ID列中显示2个值。为什么?为什么不取1个值?
  • 接下来删除第一条记录并添加新记录。在ID栏中显示3个值。为什么?为什么不取1的值呢?
  • 接下来,我使用命令'update nametable set id = 1'并收到答案,无法更新身份列ID。为什么?

3 个答案:

答案 0 :(得分:2)

使用一些代码可能更容易解释:

CREATE TABLE YourTable (ID int IDENTITY(1,1),
                        SomeCol varchar(5));

INSERT INTO dbo.YourTable (SomeCol)
VALUES('abc'); --Will get ID 1

INSERT INTO dbo.YourTable (SomeCol)
VALUES('def'),('ghi'); --Will get 2 and 3.

SELECT *
FROM dbo.YourTable;

DELETE FROM dbo.YourTable;

INSERT INTO dbo.YourTable (SomeCol)
VALUES('abc'); --Will get ID 4, because 1-3 have been used. Deleting doesn't let you reuse values.

SELECT *
FROM dbo.YourTable;

DELETE FROM dbo.YourTable;

DBCC CHECKIDENT ('dbo.YourTable', RESEED, 1);

INSERT INTO dbo.YourTable (SomeCol)
VALUES('abc'); --Will get ID 2, as you seeded back to 1; so the NEXT ID is used.

SELECT *
FROM dbo.YourTable; 

TRUNCATE TABLE dbo.YourTable;

INSERT INTO dbo.YourTable (SomeCol)
VALUES('abc'); --Will get ID 4, because 1-3 have been used.

SELECT *
FROM dbo.YourTable; --Will get ID 1, as the column was reseed with the TRUNCATE


DROP TABLE dbo.YourTable;

对于您有关播种的特定问题,将使用您定义的种子后的下一个值。您定义的种子是您所说的最后使用的种子。 Forcing the current identity value to a new value文档对此进行了介绍:

  

由于该表已有行,因此插入的下一行将使用11   作为值–为该列定义的新的当前标识值   加1(这是列的增量值)。

定义表的唯一方法是不存在行(TRUNCATE),这是我稍后在上述批处理中要做的(以及为什么要重用1)。

在一天结束时,IDENTITY的值除了为行提供单一使用值(本身不能保证唯一)之外,没有任何意义。结合主键/唯一性约束,它成为了很好的聚集索引候选对象,因为下一个值始终大于上一个使用的值,并且值不会重复使用。

如果顺序值很重要,那么您需要使用的是SEQUENCE,而不是IDENTITY属性。后者不能保证唯一性,也不能保证自己拥有顺序值(由于删除,插入失败,意外关闭等原因,它们可能会被跳过),但是它确实保证一旦使用完就不会重用值(没有RESEED):IDENTITY (Transact-SQL) - RemarksSEQUENCE可用于确保值确实是连续的(除了由于DELETE之外)。

答案 1 :(得分:1)

欢迎来到论坛:)

如果您使用创建表

Id INT IDENTITY(1,1)

然后,插入的第一个记录将具有Id = 1,但是,如果insert语句失败或事务回滚,则将使用的标识标记为已使用(或丢失),下一条insert语句将从ID = 2开始。

查看有关此主题的Microsoft文档: https://docs.microsoft.com/en-us/sql/t-sql/statements/create-table-transact-sql-identity-property?view=sql-server-2017

答案 2 :(得分:0)

在删除插入的行时(顺便说一句,在事务中回滚那些插入时也是如此),标识值不会自动重置。身份功能“记住”其最后一个值。

当从表中删除较旧的记录并将新记录插入到表中时,标识值的空白也不会被填充。

这就是身份的运作方式。这是一种简单而安全的机制。

如果您(偶尔!)希望重置身份值,则可以查看DBCC CHECKIDENT。我个人倾向于这样使用它:

DBCC CHECKIDENT (MyTable, RESEED, 0) WITH NO_INFOMSGS;
DBCC CHECKIDENT (MyTable, RESEED) WITH NO_INFOMSGS;

(我按此顺序执行两行。)

但是,我建议在生产环境中反对这种做法。