SQL Server Сбросить Идентичность Приращения для всех таблиц - PullRequest
22 голосов
/ 02 марта 2010

В основном мне нужно сбросить приращение идентичности для всех таблиц к его оригиналу. Здесь я попробовал некоторый код, но он не работает.

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 или сбросить идентичность для всех таблиц к исходной?

Ответы [ 9 ]

59 голосов
/ 02 марта 2010

У вас есть много таблиц, у которых нет начального числа и приращения 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'

Возьмите этот последний столбец в выводе и выполните эти операторы, и все готово! : -)

(по мотивам сообщения в блоге Пинала Дэйва)

12 голосов
/ 18 мая 2010

Небольшая настройка ответа marc_s.

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

Эти одиночные кавычки во всем? характер важен. Этот оператор заставит SQL Server автоматически пересчитать следующее значение идентификатора для каждой таблицы.

6 голосов
/ 26 июня 2015

Будьте осторожны при использовании этой команды, если ваша таблица содержит данные, все ваши новые вставки приведут к повторяющейся ошибке

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

чтобы решить проблему, вам нужно запустить это после этого

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

это сбросит начальное число к последнему идентификатору столбца, если данные существуют

5 голосов
/ 02 декабря 2010

Небольшая вариация, которая обрабатывает схемы немного лучше ...

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   
3 голосов
/ 24 января 2014

Другой способ использования 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 :

В следующем примере показано текущее значение идентификатора в Столбец AddressTypeID в таблице AddressType со значением 10. Поскольку в таблице есть существующие строки, следующая вставленная строка будет использовать 11 в качестве значения, то есть нового текущего значения приращения, определенного для значение столбца плюс 1

USE AdventureWorks2012;
GO
DBCC CHECKIDENT ('Person.AddressType', RESEED, 10);
GO
2 голосов
/ 29 января 2012

Для повторного заполнения ТОЛЬКО таблиц со столбцом идентификаторов вы можете использовать следующий скрипт. Он также использует 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'
2 голосов
/ 02 марта 2010

Простым способом может быть использование команды sp_MSforeachtable, недокументированной, но относительно хорошо известной команды, которая просматривает ваши таблицы.

0 голосов
/ 02 ноября 2016

(я публикую свой ответ с этой другой 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 (''?'')'

Это просто творческий способ воспользоваться комментариями из документации:

Если текущее значение идентификатора для таблицы меньше максимального Значение идентификатора хранится в столбце идентификаторов, оно сбрасывается с помощью максимальное значение в столбце идентификаторов.

0 голосов
/ 09 марта 2012

Используйте приведенный ниже код,

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