Насколько я понимаю ваш вопрос, у вас есть существующая таблица со столбцом, который до сих пор заполнялся ручными значениями, и теперь вы хотите (1) сделать этот столбец IDENTITYстолбцом и (2) убедиться, что IDENTITYзапуски от самого последнего значения в существующих строках.
Прежде всего, некоторые тестовые данные для игры:
CREATE TABLE dbo.ident_test (
id int NOT NULL,
xyz varchar(10) NOT NULL,
CONSTRAINT PK_ident_test PRIMARY KEY CLUSTERED (id)
);
INSERT INTO dbo.ident_test (id, xyz)
VALUES (1, 'test'),
(2, 'test'),
(5, 'test'),
(6, 'test'),
(10, 'test'),
(18, 'test'),
(19, 'test'),
(20, 'test');
Цель состоит в том, чтобы создать столбец первичного ключа таблицы, столбец id, IDENTITYкоторый будет начинаться с 21 для следующей вставленной записи. В этом примере столбец xyzпредставляет все остальные столбцы таблицы.
Прежде чем что-то делать, прочитайте предупреждения внизу этого поста.
Во-первых, на случай, если что-то пойдет не так:
BEGIN TRANSACTION;
Теперь давайте добавим временную рабочую колонку, id_temp и установите для этого idстолбца значения существующих столбцов:
ALTER TABLE dbo.ident_test ADD id_temp int NULL;
UPDATE dbo.ident_test SET id_temp=id;
Далее нам нужно удалить существующий idстолбец (вы не можете просто «добавить»IDENTITY существующий столбец, вы должны создать столбец как IDENTITY). Первичный ключ также должен идти, потому что столбец зависит от него.
ALTER TABLE dbo.ident_test DROP CONSTRAINT PK_ident_test;
ALTER TABLE dbo.ident_test DROP COLUMN id;
... и снова добавьте столбец, на этот раз как IDENTITY , вместе с первичным ключом:
ALTER TABLE dbo.ident_test ADD id int IDENTITY(1, 1) NOT NULL;
ALTER TABLE dbo.ident_test ADD CONSTRAINT PK_ident_test PRIMARY KEY CLUSTERED (id);
Вот где это становится интересным. Вы можете включить IDENTITY_INSERTдля таблицы, что означает, что вы можете вручную определить значения IDENTITYстолбца при вставке новых строк (однако, не обновляя существующие строки).
SET IDENTITY_INSERT dbo.ident_test ON;
С этим набором DELETEвсе строки в таблице, но строки, которые вы удаляете, находятся OUTPUTпрямо в той же самой таблице - но с определенными значениями для idстолбца (из резервного столбца).
DELETE FROM dbo.ident_test
OUTPUT deleted.id_temp AS id, deleted.xyz
INTO dbo.ident_test (id, xyz);
После этого IDENTITY_INSERTвыключите снова.
SET IDENTITY_INSERT dbo.ident_test OFF;
Удалите временный столбец, который мы добавили:
ALTER TABLE dbo.ident_test DROP COLUMN id_temp;
И, наконец, повторно заполните IDENTITYстолбец, чтобы следующая запись idвозобновилась после наибольшего существующего числа в idстолбце:
DECLARE @maxid int;
SELECT @maxid=MAX(id) FROM dbo.ident_test;
DBCC CHECKIDENT ("dbo.ident_test", RESEED, @maxid)
Проверяя таблицу примеров, наибольшее idчисло составляет 20.
SELECT * FROM dbo.ident_test;
Добавьте еще один ряд и проверьте его новый IDENTITY:
INSERT INTO dbo.ident_test (xyz) VALUES ('New row');
SELECT * FROM dbo.ident_test;
В примере новая строка будет иметь id=21. Наконец, если вы счастливы, совершите транзакцию:
COMMIT TRANSACTION;
Важный
Это не тривиальная операция, и она несет в себе довольно много рисков, о которых вам следует знать.
Сделайте это в специальной тестовой среде. Есть резервные копии. :)
Я люблю использовать BEGIN/COMMIT TRANSACTION его, потому что он предотвращает возмущение других процессов таблицей, пока вы находитесь в процессе ее изменения, и дает вам возможность откатить все назад, если что-то пойдет не так. Однако любой другой процесс, который попытается получить доступ к вашей таблице до того, как вы совершите транзакцию, будет ждать. Это может быть довольно плохо, если у вас большой стол и / или вы находитесь в производственной среде.
OUTPUT .. INTOне сработает, если у вашей целевой таблицы есть ограничения внешнего ключа или какие-либо другие функции, которые я не могу вспомнить из головы. Вместо этого вы можете вместо этого выгрузить данные во временную таблицу, а затем вставить их обратно в исходную таблицу. Возможно, вы сможете использовать переключение разделов (даже если вы не используете разделы).
Запускайте эти операторы по одному, а не в виде пакета или хранимой процедуры.
Попробуйте подумать о других вещах, которые могут зависеть от idстолбца, который вы отбрасываете и воссоздаете. Любые индексы нужно будет удалить и заново создать (как мы делали с первичным ключом). Не забудьте составить сценарий каждого индекса и ограничения, которые вам нужно будет воссоздать заранее.
Отключить любые INSERTи DELETEтриггеры на столе.
Если воссоздание таблицы является вариантом:
Если воссоздание таблицы является вариантом для вас, все намного проще:
- Создайте пустую таблицу с
id столбца в виде IDENTITY,
- Устанавливать
IDENTITY_INSERT ON для стола,
- Заполните таблицу,
- Устанавливать
IDENTITY_INSERT OFF и
- Пересмотреть личность.
IDENTITY?