我已经将记录插入到SQL Server数据库表中。该表定义了一个主键,并且自动递增标识种子被设置为“Yes”。这样做主要是因为在SQL Azure中,每个表都必须定义一个主键和标识。
但是由于我必须从表中删除一些记录,这些表的标识种子将受到干扰,索引列(自动生成的增量为1)也将受到干扰。
如何在删除记录后重置标识列,使该列具有升序数字顺序?
标识列在数据库中的任何地方都不能用作外键。
我已经将记录插入到SQL Server数据库表中。该表定义了一个主键,并且自动递增标识种子被设置为“Yes”。这样做主要是因为在SQL Azure中,每个表都必须定义一个主键和标识。
但是由于我必须从表中删除一些记录,这些表的标识种子将受到干扰,索引列(自动生成的增量为1)也将受到干扰。
如何在删除记录后重置标识列,使该列具有升序数字顺序?
标识列在数据库中的任何地方都不能用作外键。
当前回答
使用这个存储过程:
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中遇到了一个奇怪的行为,你应该知道。
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,项目1。如果在表创建后立即执行重置,则下一个值为0。老实说,我并不惊讶微软不能把这些东西做好。我发现它是因为我有一个填充引用表的脚本文件,有时在重新创建表后运行,有时在已经创建表时运行。
其他回答
发出2号命令就可以做到这一点
DBCC CHECKIDENT ('[TestTable]', RESEED,0)
DBCC CHECKIDENT ('[TestTable]', RESEED)
第一个将标识重置为零,下一个将其设置为下一个可用值 ——雅各
第一个:标识规范只是:“No”>>保存数据库执行项目
之后:身份规范只是:“是”>>保存数据库执行项目
您的数据库ID, PK从1 >>开始
我刚刚成功地使用了DBCC CHECKIDENT
注意事项:
引用表名时不接受方括号 DBCC CHECKIDENT('TableName',RESEED,n)将重置回n+1 例如,DBCC CHECKIDENT('tablename',RESEED,27)将从28开始 如果你有问题没有设置新的开始id -注意到这一点,你可以修复这个:
DECLARE @NewId as INT
SET @NewId = (SELECT MAX('TableName')-1 AS ID FROM TableName)
DBCC CHECKIDENT('TableName',RESEED,@MaxId)
虽然大多数答案都建议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。
对所有表使用这个sp:
补播“youtable”
在删除一条记录后(在触发程序中)
ALTER PROCEDURE [dbo].[RESEED](@Tabla nvarchar(100))
as
-- ********************* CREAR ESTA FUNCIÓN PRIMERO *******************************
/*
create function dbo.FN_EsIdentidad(@Tabla nvarchar(100), @Campo nvarchar(100))
returns int
as
begin
return columnproperty ( object_id ( @Tabla ), @Campo , 'IsIdentity')
end
GO
************************************************************************************
*/
declare @CampoIdentidad nvarchar(100)
SELECT @CampoIdentidad = Column_Name
--,dbo.FN_EsIdentidad(Table_Name, Column_name) as EsIdentidad,
--table_name, column_name
FROM information_schema.columns
where dbo.FN_EsIdentidad(Table_Name, Column_name) = 1
and Table_Name=@Tabla
declare @Sql nvarchar(max)
declare @OutPutNum int
set @Sql = 'Select MAX(' + @CampoIdentidad + ') From ' + @Tabla
--select @CampoIdentidad
set @sql = 'Select @ValorOut=max(' + @CampoIdentidad + ') From ' + @Tabla
declare @ParamDefinition nvarchar(max)
SET @ParamDefinition = '@ValorOut int OUTPUT'
EXECUTE sp_executesql
@SQL
,@ParamDefinition
,@ValorOut = @OutPutNum OUTPUT;
--select @OutPutNum
set @OutPutNum = coalesce(@OutPutNum ,0)
DBCC CHECKIDENT (@Tabla, RESEED, @OutputNum)