简体   繁体   中英

SQL Server Reset Identity Increment for all tables

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?

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)

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.

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   

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

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

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

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'

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

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)

(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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM