it-swarm-ko.com

SQL Server에서 레코드를 삭제 한 후 ID 시드 다시 설정

레코드를 SQL Server 데이터베이스 테이블에 삽입했습니다. 테이블에 기본 키가 정의되어 있고 자동 증가 ID 시드가 "예"로 설정되어 있습니다. 이는 주로 SQL Azure에서 각 테이블에 기본 키와 ID가 정의되어 있어야하기 때문에 수행됩니다. 

그러나 테이블에서 일부 레코드를 삭제해야하기 때문에 해당 테이블의 ID 시드가 방해 받고 인덱스 열 (1 씩 증가하여 자동 생성됨)이 방해 받게됩니다.

열을 숫자 순서로 오름차순으로 정렬하도록 레코드를 삭제 한 후 ID 열을 어떻게 다시 설정할 수 있습니까?

식별 C 럼은 데이터베이스의 외부 키로 사용되지 않습니다.

553
Romil N

DBCC CHECKIDENT 관리 명령은 ID 카운터를 재설정하는 데 사용됩니다. 명령 구문은 다음과 같습니다.

_DBCC CHECKIDENT (table_name [, { NORESEED | { RESEED [, new_reseed_value ]}}])
[ WITH NO_INFOMSGS ]
_

예:

_DBCC CHECKIDENT ('[TestTable]', RESEED, 0);
GO
_

이전 버전의 Azure SQL Database에서는 지원되지 않았지만 지금 지원됩니다.


_new_reseed_value_ 인수는 SQL Server 버전에 따라 다릅니다. 설명서에 따라 :

테이블에 행이 있으면 다음 행이 new_reseed_value 값과 함께 삽입됩니다. SQL Server 2008 R2 이전 버전에서 삽입 된 다음 행은 new_reseed_value + 현재 증분 값을 사용합니다.

그러나 관찰 된 동작은 적어도 SQL Server 2012가 여전히 new_reseed_value + 현재 증분을 사용하고 있음을 나타 내기 때문에 이 정보가 잘못된 것입니다 (실제로는 잘못 잘못됨) 가치 논리. 마이크로 소프트는 같은 페이지에있는 _Example C_ 자체와도 모순된다 :

C. 현재 아이덴티티 값을 새로운 값으로 강제

다음 예제에서는 AddressType 테이블의 AddressTypeID 열에있는 현재 ID 값을 10으로 설정합니다. 테이블에 기존 행이 있으므로 삽입 된 다음 행은 11을 값, 즉 새 현재 증분 값으로 사용합니다. 열 값에 1을 더한 값입니다.

_USE AdventureWorks2012;  
GO  
DBCC CHECKIDENT ('Person.AddressType', RESEED, 10);  
GO
_

그럼에도 불구하고 이것은 모두 최신 SQL Server 버전에서 다른 동작에 대한 옵션을 남깁니다. Microsoft가 자체 문서에서 내용을 정리할 때까지 사용하기 전에 실제 테스트를 수행하는 것이 유일한 방법이라고 생각합니다.

988
Petr Abdulin
DBCC CHECKIDENT ('TestTable', RESEED, 0)
GO

여기서 0은 identity 시작 값

188
anil shah

데이터의 IF all DELETE (즉, WHERE 절이 없음)을 통해 테이블에서 제거되는 경우 a) 권한이 허용하는 한 b) FK가 없음을 유의해야합니다 TRUNCATE TABLE를 사용하여 테이블을 참조하는 것이 선호 될 것입니다. 왜냐하면 더 효율적인 DELETEIDENTITY 시드를 동시에 재설정하기 때문입니다. 다음 세부 정보는 TRUNCATE TABLE 에 대한 MSDN 페이지에서 가져온 것입니다.

TRUNCATE TABLE에는 DELETE 문과 비교할 때 다음과 같은 이점이 있습니다.

  • 더 적은 트랜잭션 로그 공간이 사용됩니다.

    DELETE 문은 한 번에 하나씩 행을 제거하고 삭제 된 각 행에 대한 트랜잭션 로그에 항목을 기록합니다. TRUNCATE TABLE은 테이블 데이터를 저장하는 데 사용 된 데이터 페이지를 할당 해제하여 데이터를 제거하고 페이지 할당 취소 만 트랜잭션 로그에 기록합니다.

  • 자주 사용되는 잠금이 적습니다.

    행 잠금을 사용하여 DELETE 문을 실행하면 테이블의 각 행이 잠겨 삭제됩니다. TRUNCATE TABLE은 항상 테이블 (SCH-M 잠금 포함)과 각 행이 아닌 페이지를 잠급니다.

  • 예외없이 테이블에 제로 페이지가 남아 있습니다.

    DELETE 문이 실행 된 후에도 테이블에는 여전히 빈 페이지가 포함될 수 있습니다. 예를 들어, 힙의 빈 페이지는 배타적 (LCK_M_X) 테이블 잠금이 없으면 할당을 해제 할 수 없습니다. 삭제 작업에서 테이블 잠금을 사용하지 않으면 테이블 (힙)에 빈 페이지가 많이 포함됩니다. 인덱스의 경우, 삭제 작업은 빈 페이지를 뒤에 남겨 둘 수 있지만, 이러한 페이지는 백그라운드 정리 프로세스에 의해 신속하게 할당 취소됩니다.

테이블에 ID 열이 있으면 해당 열의 카운터가 열에 대해 정의 된 시드 값으로 다시 설정됩니다. 시드가 정의되지 않은 경우 기본값 1이 사용됩니다. ID 카운터를 유지하려면 대신 DELETE를 사용하십시오.

그래서 다음과 같습니다 :

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

된다.

TRUNCATE TABLE [MyTable];

제약 등에 관한 추가 정보는 위의 링크 된 TRUNCATE TABLE 문서를 참조하십시오.

71
Solomon Rutzky

대부분의 답변은 RESEED를 0으로 제안하지만, 다음 번 ID를 다시 사 용할 때가 많습니다.

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로 재설정됩니다.

62
Atal Kishore

나는 @anil shahs 대답을 시도하고 신원을 다시 설정합니다. 그러나 새로운 행이 삽입되면 identity = 2를 얻습니다. 대신 구문을 다음과 같이 변경했습니다.

DELETE FROM [TestTable]

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

그런 다음 첫 번째 행에 ID = 1이 생깁니다.

57
Mikael Engver

대부분의 답변은 RESEED0로 제안하지만 일부는이를 TRUNCATED 테이블의 결함으로 보는 반면 Microsoft는 ID을 제외하는 솔루션을 제공합니다

DBCC CHECKIDENT ('[TestTable]', RESEED)

이렇게하면 테이블을 확인하고 다음 ID로 재설정됩니다. 이것은 현재까지 MS SQL 2005부터 사용 가능합니다.

https://msdn.Microsoft.com/en-us/library/ms176057.aspx

15
SollyM

@jacob

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

나를 위해 일한, 난 그냥 테이블에서 모든 항목을 먼저 지우고 삭제 후 트리거 지점에서 위의 추가했다. 지금은 항목을 삭제할 때마다 거기에서 가져옵니다.

5
epic

새로운 ID로 ID 열 재설정 ...

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

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

발급 2 명령 트릭을 할 수있는

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

첫 번째는 ID를 0으로 재설정하고, 다음은 사용 가능한 다음 값으로 설정합니다. - jacob

4
jacob

이것은 일반적인 질문이며 답변은 항상 동일합니다.하지 마십시오. 신원 값은 임의적으로 취급되어야하며, 따라서 "올바른"주문이 없습니다.

4
Ben Thul

Truncate 테이블은 레코드를 지우고 카운터를 재설정하고 dis 공간을 회수하기 때문에 선호됩니다. 

DeleteCheckIdent은 외부 키가자를 수없는 경우에만 사용해야합니다.

3
Dyna Dave

이 스크립트를 실행하여 ID 열을 재설정하십시오. 두 가지를 변경해야합니다. tableXYZ를 업데이트해야하는 테이블로 바꾸십시오. 또한 식별 컬럼의 이름은 임시 테이블에서 제거해야합니다. 이것은 35,000 개의 행과 3 개의 열이있는 테이블에서 즉시 발생했습니다. 분명히, 테이블을 백업하고 먼저 테스트 환경에서 이것을 시도하십시오. 


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
2
Matthew Baic

이 저장 프로 시저를 사용하십시오.

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 서버 2008 r2에서 이상한 행동을 가로 질러 왔어.

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이됩니다. 솔직히 Microsoft는이 문제를 올바르게 처리 할 수 ​​없다는 사실에 놀라지 않습니다. 내가 테이블을 다시 생성 한 후 가끔씩 실행되는 참조 테이블을 채우는 스크립트 파일이 있고 테이블이 이미 만들어져 있기 때문에 발견했습니다.

1
costa

테이블 전체를 정리하지 않는 한 0으로 다시 시드하는 것은 실용적이지 않습니다.

다른 현명한 Anthony Raymond의 답변은 완벽합니다. 최대 식별 열을 먼저 얻은 다음 최대로 시드하십시오.

0
Ali Sufyan

행을 완전히 삭제하고 IDENTITY 개수를 다시 설정하려면이 (SQL Server 2008 R2)

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
0
Fandango68

다음 스크립트를 사용하여이 작업을 수행합니다. 테이블에서 모든 행을 삭제하고 "IDENT_CURRENT"가 현재 1로 설정되어있는 경우 (즉, 테이블에 행이 하나만있는 경우)와 같은 "오류"가 발생하는 시나리오는 하나뿐입니다.

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)
;
0
Chris Mack
DBCC CHECKIDENT (<TableName>, reseed, 0)

그러면 현재 ID 값이 0으로 설정됩니다.

다음 값을 삽입하면 ID 값이 1로 증가합니다.

0
Bimzee