28

基本上我需要将所有表的标识增量重置为其原始值。在这里,我尝试了一些代码,但失败了。

http://pastebin.com/KSyvtK5b

链接中的实际代码:

USE World00_Character
GO

-- Create a cursor to loop through the System Ojects and get each table name
DECLARE TBL_CURSOR CURSOR
-- Declare the SQL Statement to cursor through
FOR ( SELECT Name FROM Sysobjects WHERE Type='U' )

-- Declare the @SQL Variable which will hold our dynamic sql
DECLARE @SQL NVARCHAR(MAX);
SET @SQL = '';
-- Declare the @TblName Variable which will hold the name of the current table
DECLARE @TblName NVARCHAR(MAX);

-- Open the Cursor
OPEN TBL_CURSOR

-- Setup the Fetch While that will loop through our cursor and set @TblName
FETCH NEXT FROM TBL_CURSOR INTO @TblName
-- Do this while we are not at the end of the record set
WHILE (@@FETCH_STATUS <> -1)
BEGIN
-- Appeand this table's select count statement to our sql variable
SET @SQL = @SQL + ' ( SELECT '''+@TblName+''' AS Table_Name,COUNT(*) AS Count FROM '+@TblName+' ) UNION';

-- Delete info
EXEC('DBCC CHECKIDENT ('+@TblName+',RESEED,(SELECT IDENT_SEED('+@TblName+')))');

-- Pull the next record
FETCH NEXT FROM TBL_CURSOR INTO @TblName
-- End the Cursor Loop
END

-- Close and Clean Up the Cursor
CLOSE TBL_CURSOR
DEALLOCATE TBL_CURSOR

-- Since we were adding the UNION at the end of each part, the last query will have
-- an extra UNION. Lets  trim it off.
SET @SQL = LEFT(@SQL,LEN(@SQL)-6);

-- Lets do an Order By. You can pick between Count and Table Name by picking which
-- line to execute below.
SET @SQL = @SQL + ' ORDER BY Count';
--SET @SQL = @SQL + ' ORDER BY Table_Name';

-- Now that our Dynamic SQL statement is ready, lets execute it.
EXEC (@SQL);
GO

错误信息:

Error: Msg 102, Level 15, State 1, Line 1 Incorrect syntax near '('.

如何修复该 SQL 或将所有表的标识重置为其原始标识?

4

11 回答 11

68

你有很多表没有种子和增量 1 吗?

如果没有(默认情况下,所有表都有),请使用以下代码:

exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT(''?'', RESEED, 1)'

MSforeachtable是一个未记录但非常方便的存储过程,它对数据库中的所有表执行给定的命令。

如果您需要绝对准确,请使用此语句 - 它会生成一个 SQL 语句列表,以将所有表重新设置为原始 SEED 值:

SELECT 
    IDENT_SEED(TABLE_NAME) AS Seed,
    IDENT_INCR(TABLE_NAME) AS Increment,
    IDENT_CURRENT(TABLE_NAME) AS Current_Identity,
    TABLE_NAME,
    'DBCC CHECKIDENT(' + TABLE_NAME + ', RESEED, ' + CAST(IDENT_SEED(TABLE_NAME) AS VARCHAR(10)) + ')'
FROM 
    INFORMATION_SCHEMA.TABLES
WHERE 
    OBJECTPROPERTY(OBJECT_ID(TABLE_NAME), 'TableHasIdentity') = 1
    AND TABLE_TYPE = 'BASE TABLE'

抓住输出中的最后一列,并执行这些语句,你就完成了!:-)

(灵感来自Pinal Dave的博客文章)

于 2010-03-02T16:36:23.557 回答
14

对 marc_s 答案稍作调整。

exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT (''?'', RESEED)'

周围的那些单引号?性格很重要。该语句将导致 SQL Server 自动重新计算每个表的下一个标识值。

于 2010-05-18T14:47:38.573 回答
8

处理模式的轻微变化更好......

SELECT 
    IDENT_SEED(TABLE_SCHEMA+'.'+TABLE_NAME) AS Seed,
    IDENT_INCR(TABLE_SCHEMA+'.'+TABLE_NAME) AS Increment,
    IDENT_CURRENT(TABLE_SCHEMA+'.'+TABLE_NAME) AS Current_Identity,
    TABLE_SCHEMA+'.'+TABLE_NAME,
    'DBCC CHECKIDENT('''+TABLE_SCHEMA+'.'+TABLE_NAME+''', RESEED, '+CAST(IDENT_SEED(TABLE_SCHEMA+'.'+TABLE_NAME) AS VARCHAR(10))+')'
FROM 
    INFORMATION_SCHEMA.TABLES
WHERE 
    OBJECTPROPERTY(OBJECT_ID(TABLE_SCHEMA+'.'+TABLE_NAME), 'TableHasIdentity') = 1
AND TABLE_TYPE = 'BASE TABLE'
ORDER BY TABLE_SCHEMA, TABLE_NAME   
于 2010-12-02T15:27:29.230 回答
7

如果您的表包含数据,则使用此命令时要小心,所有新插入都会导致重复错误

exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT(''?'', RESEED,1)'

要解决您需要在此之后运行的问题

exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT(''?'', RESEED)'

如果数据存在,这会将种子重置为最后一个列标识

于 2015-06-25T22:13:20.567 回答
3

sp_MSForEachTable在重置表之前使用和检查表是否具有标识值的另一种方法:

EXEC sp_MSForEachTable '
 Print ''?''
 IF OBJECTPROPERTY(object_id(''?''), ''TableHasIdentity'') = 1
  DBCC CHECKIDENT (''?'', RESEED, 0)
 else
  Print ''Table does not have an identity value''
'

注意:如果您希望标识值从 1 开始,则 DBCC 命令应使用CHECKIDENT (''?'', RESEED, 0)not CHECKIDENT (''?'', RESEED, 1),如某些答案中所示。引用MS SQL Server 文档

以下示例将 AddressType 表中 AddressTypeID 列中的当前标识值强制为值 10。由于该表已存在行,因此插入的下一行将使用 11 作为值,即为定义的新的当前增量值列值加 1

USE AdventureWorks2012;
GO
DBCC CHECKIDENT ('Person.AddressType', RESEED, 10);
GO
于 2014-01-24T13:04:01.333 回答
2

一个简单的方法可能是使用 sp_MSforeachtable 命令,这是一个未记录但相对广为人知的命令,用于查看您的表。

于 2010-03-02T16:37:20.180 回答
2

要只为带有标识列的表重新设置种子,您可以使用下一个脚本。它还利用sp_MSforeachtable但考虑到正确的表格。

EXEC sp_MSforeachtable '
IF (SELECT COUNT(1) 
    FROM INFORMATION_SCHEMA.TABLES 
    WHERE TABLE_TYPE = ''BASE TABLE'' 
    AND ''[''+ TABLE_SCHEMA + ''].['' + TABLE_NAME + '']'' = ''?'' 
    AND OBJECTPROPERTY(OBJECT_ID(TABLE_NAME), ''TableHasIdentity'') = 1) > 0 
BEGIN
    DBCC CHECKIDENT (''?'', RESEED, 1)
END'
于 2012-01-28T20:44:46.193 回答
1

我们在工作中计划了停电,出于某种原因,我的一些表在其身份列中跃升了 1000。我修改了此代码以创建一个选择字符串列表,以显示与当前标识相比列的当前值。然后我将这些行复制并粘贴到另一个选择中。

    SELECT 
        Replace(CurrentValue,'FROM',','+ CAST(IDENT_CURRENT(TABLE_SCHEMA+'.'+TABLE_NAME)AS VARCHAR) + ' AS Current_Identity FROM')
    FROM 
        INFORMATION_SCHEMA.TABLES T left join (select 'UNION SELECT ''DBCC CHECKIDENT(''''['+TABLE_SCHEMA+'].'+TABLE_NAME+''''', RESEED, ''+CAST( MAX('+COLUMN_NAME+') as VARCHAR)+'')'' as DBCC_String,MAX('+COLUMN_NAME+') as CurrentValue FROM [' + TABLE_SCHEMA+'].'+TABLE_NAME as CurrentValue,TABLE_SCHEMA+'.'+TABLE_NAME as TTABLE
        from INFORMATION_SCHEMA.COLUMNS
        where COLUMNPROPERTY(object_id(TABLE_SCHEMA+'.'+TABLE_NAME), COLUMN_NAME, 'IsIdentity') = 1 
        ) as TT on T.TABLE_SCHEMA+'.'+T.TABLE_NAME = TT.TTABLE
    WHERE 
        OBJECTPROPERTY(OBJECT_ID(TABLE_SCHEMA+'.'+TABLE_NAME), 'TableHasIdentity') = 1
    AND TABLE_TYPE = 'BASE TABLE'
    ORDER BY T.TABLE_SCHEMA, T.TABLE_NAME  

然后将选定的列复制到

    select DBCC_String,CurrentValue,Current_Identity from
    (
     *Paste Here and delete the first "UNION"*
    ) as T where CurrentValue < Current_Identity

然后你可以从表中复制 DBC_String 列 来修改你需要的表

于 2021-03-19T16:56:30.860 回答
0

使用下面的代码,

CREATE TABLE #tmptable
(
    [seednvalue] int not null,
    [tablename] [nvarchar] (100) NULL
) 


declare @seedvalue AS INT
DECLARE @tablename AS VARCHAR(100)

Declare #tablesIdentityCursor CURSOR
    for 
    SELECT 
    IDENT_CURRENT(TABLE_NAME)+1 AS Current_Identity,
    TABLE_NAME
    FROM INFORMATION_SCHEMA.TABLES
    WHERE OBJECTPROPERTY(OBJECT_ID(TABLE_NAME), 'TableHasIdentity') = 1
    AND TABLE_TYPE = 'BASE TABLE'  --AND TABLE_NAME='test11'

delete from #tmptable
Open #tablesIdentityCursor
FETCH NEXT FROM #tablesIdentityCursor into @seedvalue, @tablename
WHILE @@FETCH_STATUS = 0 BEGIN

    Insert into #tmptable Select @seedvalue , @tablename   
    DBCC CHECKIDENT (@tablename, reseed, @seedvalue) 
    FETCH NEXT FROM #tablesIdentityCursor into @seedvalue, @tablename
END
CLOSE #tablesIdentityCursor
DEALLOCATE #tablesIdentityCursor
SELECT * FROM #tmptable
DROP TABLE #tmptable
于 2012-03-09T14:33:47.067 回答
0

(我正在从另一个 SO 页面重新发布我的答案)

也许最简单的方法(就像这听起来很疯狂,而且看起来很臭)就是DBCC CHECKIDENT像这样运行两次:

-- sets all the seeds to 1
exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT (''?'', RESEED, 1)'

-- run it again to get MSSQL to figure out the MAX/NEXT seed automatically
exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT (''?'')'

完毕。

如果需要,您可以再次运行它以查看所有种子的设置:

-- run it again to display what the seeds are now set to
exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT (''?'')'

这只是利用文档中的评论的一种创造性方式:

如果表的当前标识值小于标识列中存储的最大标识值,则使用标识列中的最大值对其进行重置。

于 2016-11-02T16:11:05.937 回答
0
declare @sqlcommand varchar(max) = '';

SELECT 
    @sqlcommand =@sqlcommand 
    + 'select @max=isnull(max('+i.name+'),0) from '+t.name+';'
    + 'DBCC CHECKIDENT ('''+t.name+''', RESEED, @max);' 
FROM sys.tables AS t
inner join sys.identity_columns as i on i.[object_id] = t.[object_id]

set @sqlcommand = 'declare @max int;'+@sqlcommand;
EXEC(@sqlcommand)
于 2022-02-16T19:04:54.617 回答