SQL Server 重置所有表的标识增量

发布于 2024-08-23 16:16:52 字数 1897 浏览 7 评论 0原文

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

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 或将所有表的身份重置为其原始身份?

Basically I need to reset Identity Increment for all tables to its original.
Here I tried some code, but it fails.

http://pastebin.com/KSyvtK5b

Actual code from link:

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 message:

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

How can I either fix that SQL or reset identity for all tables to its original?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

稳稳的幸福 2024-08-30 16:16:52

您是否有很多没有种子且增量为 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)

Do you have lots of tables which do not have a seed and increment of 1 ??

If not (by default, all tables have that), use this code:

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

MSforeachtable is an undocumented, but extremely handy stored proc which executes a given command against all tables in your database.

If you need to be absolutely exact, use this statement - it will generate a list of SQL statements to reseed all tables to their original SEED value:

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'

Grab that last column in the output, and execute those statements and you're done! :-)

(inspired by a blog post by Pinal Dave)

她如夕阳 2024-08-30 16:16:52

对 marc_s 的答案稍作调整。

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

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

Slight tweak on marc_s answer.

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

Those single-quotes around the ? character are important. That statement will cause SQL Server to automatically recalculate the next identity value for each table.

み零 2024-08-30 16:16:52

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

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   

Slight variation that handles Schemas a bit better...

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   
撞了怀 2024-08-30 16:16:52

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

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

以解决您需要运行此命令的问题,

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

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

Be careful when using this command if your table contains data all your new inserts will result duplicate error

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

to solve the problem you need to run this after that

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

this will reset the seed to the last column identity if the data exists

暮光沉寂 2024-08-30 16:16:52

要仅对具有标识列的表重新设定种子,您可以使用下一个脚本。
它还使用 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'

To reseed ONLY tables with an identity column you can use the next script.
It also makes use of sp_MSforeachtable but taking into account the correct tables.

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'
半衾梦 2024-08-30 16:16:52

使用 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) 而不是 CHECKIDENT (''?'', RESEED, 1),如某些答案中所示。引自 MS SQL Server 文档

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

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

Another way of using sp_MSForEachTable and checking whether or not the Table has an identity value before resetting it:

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

NOTE: If you want the identity value to start at 1 then the DBCC command should use CHECKIDENT (''?'', RESEED, 0) not CHECKIDENT (''?'', RESEED, 1) as indicated in some of the answers. Quote from MS SQL Server documentation:

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

USE AdventureWorks2012;
GO
DBCC CHECKIDENT ('Person.AddressType', RESEED, 10);
GO
葬﹪忆之殇 2024-08-30 16:16:52

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

An easy metod may be to use the sp_MSforeachtable command, an undocumented, but relatively well know command that looks over your tables.

小苏打饼 2024-08-30 16:16:52

我的工作场所按计划停电,不知出于什么原因,我的一些表的身份列中的数字跃升了 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 列
Table 修改您需要的表格

We had a scheduled power outage at my work and for what ever reason some of my tables had jumped by 1000 in their Identity Column.
I modified this code to make a list of select strings to show the current Value of the column compared to the Current Identity.
I then copy and pasted the rows into another selection.

    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  

Then copy the selected column inside of

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

then you can copy the DBC_String column from the
Table to modify the tables you need

夏尔 2024-08-30 16:16:52
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)
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)
も星光 2024-08-30 16:16:52

使用下面的代码,

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

Use the below code,

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
另类 2024-08-30 16:16:52

(我从另一个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 (''?'')'

这只是利用文档中的注释的一种创造性方法:

如果表的当前标识值小于最大值
标识值存储在标识列中,使用以下命令重置它
标识列中的最大值。

(I'm reposting my answer from this other SO page)

Perhaps the easiest way (as crazy as this sounds and as code-smelly as it looks) is to just run DBCC CHECKIDENT twice like this:

-- 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 (''?'')'

Done.

If you want, you can run it once more to see what all the seeds were set to:

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

This is just a creative way to take advantage of the comment from the documentation:

If the current identity value for a table is less than the maximum
identity value stored in the identity column, it is reset using the
maximum value in the identity column.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文