The currently accepted answer only explains this annoying phenomenon. Only one answer offers some sort of a solution, but not really practical because it requires a dummy insertion, which makes it hard to generalize.
The only generic solution is to reseed the identity value, then check the current identity value and reseed it again when it's 0. This can be done by a stored procedure:
CREATE OR ALTER PROCEDURE ReseedIdentity
@tableName SYSNAME
AS
BEGIN
DBCC CHECKIDENT(@tableName, RESEED, 0)
IF IDENT_CURRENT(@tableName) = 0
BEGIN
DBCC CHECKIDENT(@tableName, RESEED, 1)
END
END
This will always start new records at identity value 1, whether it's a new table, after truncating or after deleting all records.
If there are identity specifications starting at higher seed values a somewhat more advanced version can be used, which is a generalization of the former:
CREATE OR ALTER PROCEDURE ReseedIdentity
@tableName SYSNAME
AS
BEGIN
DECLARE @seed NUMERIC(18,0) = IDENT_SEED(@tableName) - 1;
DBCC CHECKIDENT(@tableName, RESEED, @seed)
IF IDENT_CURRENT(@tableName) = @seed
BEGIN
SET @seed = @seed + 1
DBCC CHECKIDENT(@tableName, RESEED, @seed)
END
END