删除SQL Server中的记录后重置标识种子

Reset identity seed after deleting records in SQL Server

我已将记录插入到SQL Server数据库表中。该表定义了一个主键,并且自动递增标识种子设置为"是"。这主要是因为在SQLAzure中,每个表都必须定义一个主键和标识。

但是由于我必须从表中删除一些记录,这些表的标识种子将受到干扰,索引列(增量为1时自动生成)将受到干扰。

如何在删除记录后重置标识列,以使该列具有升序数字顺序?

标识列未用作数据库中任何位置的外键。


DBCC CHECKIDENT管理指挥的身份是用来重置计数器。命令的语法是:

1
2
DBCC CHECKIDENT (TABLE_NAME [, { NORESEED | { RESEED [, new_reseed_value ]}}])
[ WITH NO_INFOMSGS ]

例子:

1
2
DBCC CHECKIDENT ('[TestTable]', RESEED, 0);
GO

它是在以前的版本不支持SQL Azure数据库A大学,但现在是支持的。

请注意,在SQL Server new_reseed_value论点是根据不同版本的文档:

If rows are present in the table, the next row is inserted with the new_reseed_value value. In version SQL Server 2008 R2 and earlier, the next row inserted uses new_reseed_value + the current increment value.

然而,我发现这对于成本(只是平原是错误的信息,因为观察到的行为表明),至少是不使用SQL Server 2012年新_ reseed _值+当前增量的价值逻辑。微软甚至有其自己的contradicts Example C发现在相同的页面:

C. Forcing the current identity value to a new value

The following example forces the current identity value in the
AddressTypeID column in the AddressType table to a value of 10.
Because the table has existing rows, the next row inserted will use 11
as the value, that is, the new current increment value defined for the
column value plus 1.

1
2
3
4
USE AdventureWorks2012;  
GO  
DBCC CHECKIDENT ('Person.AddressType', RESEED, 10);  
GO

安静,这所有的叶子在不同的行为选择对新的SQL Server版本。我想唯一的方式来确保清晰的东西在动,直到微软自己的文档,是做实际测试之前使用。


1
2
DBCC CHECKIDENT ('TestTable', RESEED, 0)
GO

identity启动值是0


应该指出,如果所有的数据是删除从表(IU)以DELETENO WHERE条款),然后只要a)权限允许的信息,和(b)没有看见引用表(这似乎是的情况,在这里,它是首选使用TRUNCATE TABLE如何更高效DELETE和复位在identity种子在同一时间。下面是从MSDN的细节和页表的截断

Compared to the DELETE statement, TRUNCATE TABLE has the following advantages:

  • Less transaction log space is used.

    The DELETE statement removes rows one at a time and records an entry in the transaction log for each deleted row. TRUNCATE TABLE removes the data by deallocating the data pages used to store the table data and records only the page deallocations in the transaction log.

  • Fewer locks are typically used.

    When the DELETE statement is executed using a row lock, each row in the table is locked for deletion. TRUNCATE TABLE always locks the table (including a schema (SCH-M) lock) and page but not each row.

  • Without exception, zero pages are left in the table.

    After a DELETE statement is executed, the table can still contain empty pages. For example, empty pages in a heap cannot be deallocated without at least an exclusive (LCK_M_X) table lock. If the delete operation does not use a table lock, the table (heap) will contain many empty pages. For indexes, the delete operation can leave empty pages behind, although these pages will be deallocated quickly by a background cleanup process.

If the table contains an identity column, the counter for that column is reset to the seed value defined for the column. If no seed was defined, the default value 1 is used. To retain the identity counter, use DELETE instead.

那么下面的:

1
2
DELETE FROM [MyTable];
DBCC CHECKIDENT ('[MyTable]', RESEED, 0);

成就:

1
TRUNCATE TABLE [MyTable];

TRUNCATE TABLE文档(湖联以上)额外的信息的限制,等等。


我们建议的答案是最reseed为0,但许多次我们需要准时到下一个reseed ID

1
2
3
4
5
DECLARE @MAX INT
SELECT @MAX=MAX([Id])FROM [TestTable]
IF @MAX IS NULL   //CHECK WHEN MAX IS returned AS NULL
  SET @MAX = 0
DBCC CHECKIDENT ('[TestTable]', RESEED,@MAX)

这将重置检查表和下一个ID。


我想把它@anil shahs复位的识别.但当新插入的行上有identity = 2什么信息。因此,而不是一个语法:

1
2
3
4
DELETE FROM [TestTable]

DBCC CHECKIDENT ('[TestTable]', RESEED, 0)
GO

然后第一行要把形象= 1。


虽然大多数的答案是对是RESEED0湖,当一些漏洞TRUNCATED表为本作为一个解决方案,微软有一个排除的ID

1
DBCC CHECKIDENT ('[TestTable]', RESEED)

这将检查表和一ID重置。本已可自MS SQL 2005的电流。

http://。/en-US /图书馆/ ms176057.aspx


这是一个普通的问题,答案总是一样的:Don’t做它。标识应为任意值的搜索和处理,即,没有"正确"的命令。


"雅各

1
2
DBCC CHECKIDENT ('[TestTable]', RESEED,0)
DBCC CHECKIDENT ('[TestTable]', RESEED)

为我工作,我不得不先清除所有条目从表A中,然后添加上面的触发点后删除。现在每当我删除条目是在采取从那里。


2发布命令可以做的把戏

1
2
DBCC CHECKIDENT ('[TestTable]', RESEED,0)
DBCC CHECKIDENT ('[TestTable]', RESEED)

第一复位的零和一的身份,希望它的下一个值的集合-雅各布


因为它将是首选的Truncate表记录,计数器复位和回收的磁盘空间。

DELETECheckIdent应仅用于防止你从哪里truncating外键。


一个新的ID识别柱复位。

1
2
3
4
DECLARE @MAX INT
SELECT @MAX=ISNULL(MAX(Id),0) FROM [TestTable]

DBCC CHECKIDENT ('[TestTable]', RESEED,@MAX)


运行一个脚本识别柱复位。你需要做的两个变化。无论你需要tablexyz replace一表更新。所以,需要把名字识别柱表没有温度。这是一个新的表行瞬时&;3列。显然,这与第一次备份表中的测试环境。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
SELECT *
INTO #temp
FROM tableXYZ

SET identity_insert tableXYZ ON

TRUNCATE TABLE tableXYZ

ALTER TABLE #temp DROP COLUMN (nameOfIdentityColumn)

SET identity_insert tableXYZ OFF

INSERT INTO tableXYZ
SELECT * FROM #temp


使用此存储过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
IF (object_id('[dbo].[pResetIdentityField]') IS NULL)
  BEGIN
    EXEC('CREATE PROCEDURE [dbo].[pResetIdentityField] AS SELECT 1 FROM DUMMY');
  END
GO

SET  ANSI_NULLS ON
GO
SET  QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[pResetIdentityField]
  @pSchemaName NVARCHAR(1000)
, @pTableName NVARCHAR(1000) AS
DECLARE @MAX   INT;
DECLARE @fullTableName   NVARCHAR(2000) = @pSchemaName + '.' + @pTableName;

DECLARE @identityColumn   NVARCHAR(1000);

SELECT @identityColumn = c.[name]
FROM sys.tables t
     INNER JOIN sys.schemas s ON t.[schema_id] = s.[schema_id]
     INNER JOIN sys.columns c ON c.[object_id] = t.[object_id]
WHERE     c.is_identity = 1
      AND t.name = @pTableName
      AND s.[name] = @pSchemaName

IF @identityColumn IS NULL
  BEGIN
    RAISERROR(
      'One of the following is true: 1. the table you specified doesn''t have an identity field, 2. you specified an invalid schema, 3. you specified an invalid table'
    , 16
    , 1);
    RETURN;
  END;

DECLARE @sqlString   NVARCHAR(MAX) = N'SELECT @maxOut = max(' + @identityColumn + ') FROM ' + @fullTableName;

EXECUTE sp_executesql @stmt = @sqlString, @params = N'@maxOut int OUTPUT', @maxOut = @MAX OUTPUT

IF @MAX IS NULL
  SET @MAX = 0

print(@MAX)

DBCC CHECKIDENT (@fullTableName, RESEED, @MAX)
GO

--exec pResetIdentityField 'dbo', 'Table'

只是回顾一下我的答案。我在SQL Server 2008 R2中遇到了一个您应该注意的奇怪行为。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
DROP TABLE test01

CREATE TABLE test01 (Id INT IDENTITY(1,1), descr nvarchar(10))

EXECUTE pResetIdentityField 'dbo', 'test01'

INSERT INTO test01 (descr) VALUES('Item 1')

SELECT * FROM test01

DELETE FROM test01

EXECUTE pResetIdentityField 'dbo', 'test01'

INSERT INTO test01 (descr) VALUES('Item 1')

SELECT * FROM test01

第一个选择产生0, Item 1

第二个产生1, Item 1。如果在创建表后立即执行重置,则下一个值为0。老实说,我并不惊讶微软不能正确处理这些问题。我发现它是因为我有一个脚本文件,它填充引用表,我有时在重新创建表后运行,有时在已经创建表时运行。


1
DBCC CHECKIDENT (<TableName>, reseed, 0)

本想流标识值设置为0。

在一inserting价值、形象价值incremented get to 1。


我使用下面的脚本来执行此操作。只有一种情况会产生"错误",即如果删除了表中的所有行,并且IDENT_CURRENT当前设置为1,即表中只有一行要开始。

1
2
3
4
5
6
7
8
9
10
11
12
DECLARE @maxID INT = (SELECT MAX(ID) FROM dbo.Tbl)
;

IF @maxID IS NULL
    IF (SELECT IDENT_CURRENT('dbo.Tbl')) > 1
        DBCC CHECKIDENT ('dbo.Tbl', RESEED, 0)
    ELSE
        DBCC CHECKIDENT ('dbo.Tbl', RESEED, 1)
    ;
ELSE
    DBCC CHECKIDENT ('dbo.Tbl', RESEED, @maxID)
;

对于完整的删除行和重置标识计数,我使用这个(SQL Server 2008 R2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
USE mydb

-- ##################################################################################################################
-- DANGEROUS!!!! USE WITH CARE
-- ##################################################################################################################

DECLARE
  db_cursor CURSOR FOR
    SELECT TABLE_NAME
      FROM INFORMATION_SCHEMA.TABLES
     WHERE TABLE_TYPE = 'BASE TABLE'
       AND TABLE_CATALOG = 'mydb'

DECLARE @tblname VARCHAR(50)
SET @tblname = ''

OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @tblname

WHILE @@FETCH_STATUS = 0
BEGIN
  IF CHARINDEX('mycommonwordforalltablesIwanttodothisto', @tblname) > 0
    BEGIN
      EXEC('DELETE FROM ' + @tblname)
      DBCC CHECKIDENT (@tblname, RESEED, 0)
    END

  FETCH NEXT FROM db_cursor INTO @tblname
END

CLOSE db_cursor
DEALLOCATE db_cursor
GO


它总是最好使用TRUNCATE可能不是通过您的所有记录,当它不使用,所以日志空间。

我们需要删除的情况和需要复位的种子,永远记住,如果你使用的是不populated表DBCC CHECKIDENT('tablenem',RESEED,0)然后,第一形象记录想得到=0他一定在MSDN文档

In your case only rebuild the index and don't worry about losing the
series of identity as this is a common scenario.


第一:标识规范只是:"否">>保存数据库执行项目

之后:标识规范只是:"是">>保存数据库执行项目

您的数据库ID,pk从1开始>>