SQL Server, Как установить автоматическое увеличение после создания таблицы без потери данных?
У меня есть таблица table1
в SQL Server 2008, и в ней есть записи.
Я хочу, чтобы столбец первичного ключа table1_Sno
был автоматически увеличивающимся столбцом. Это можно сделать без какой-либо передачи данных или клонирования таблицы?
Я знаю, что я могу использовать ALTER TABLE для добавления столбца автоинкремент, но могу ли я просто добавить параметр AUTO_INCREMENT в существующий столбец, который является первичным ключом?
Ответы
Ответ 1
Изменение свойства IDENTITY
- это действительно изменение только метаданных. Но для немедленного обновления метаданных необходимо запустить экземпляр в режиме одиночного пользователя и возиться с некоторыми столбцами в sys.syscolpars
и недокументирован/неподдерживается, а не что-то, что я бы рекомендовал или предоставит дополнительные сведения о нем.
Для людей, которые сталкиваются с этим ответом на SQL Server 2012+, самым простым способом достижения этого результата автоинкрементного столбца было бы создание объекта SEQUENCE
и установка next value for seq
в качестве столбца по умолчанию.
В качестве альтернативы или для предыдущих версий (начиная с 2005 года) обходное решение, опубликованное на этом элементе подключения, показывает полностью поддерживаемый способ сделать это без любая потребность в размере операций с данными с помощью ALTER TABLE...SWITCH
. Также blogged about на MSDN здесь. Хотя код для достижения этого не очень прост и существуют ограничения - например, измененная таблица не может быть целью ограничения внешнего ключа.
Пример кода.
Настройка тестовой таблицы без столбца IDENTITY
.
CREATE TABLE dbo.tblFoo
(
bar INT PRIMARY KEY,
filler CHAR(8000),
filler2 CHAR(49)
)
INSERT INTO dbo.tblFoo (bar)
SELECT TOP (10000) ROW_NUMBER() OVER (ORDER BY (SELECT 0))
FROM master..spt_values v1, master..spt_values v2
Измените его, чтобы иметь столбец IDENTITY
(более или менее мгновенный).
BEGIN TRY;
BEGIN TRANSACTION;
/*Using DBCC CHECKIDENT('dbo.tblFoo') is slow so use dynamic SQL to
set the correct seed in the table definition instead*/
DECLARE @TableScript nvarchar(max)
SELECT @TableScript =
'
CREATE TABLE dbo.Destination(
bar INT IDENTITY(' +
CAST(ISNULL(MAX(bar),0)+1 AS VARCHAR) + ',1) PRIMARY KEY,
filler CHAR(8000),
filler2 CHAR(49)
)
ALTER TABLE dbo.tblFoo SWITCH TO dbo.Destination;
'
FROM dbo.tblFoo
WITH (TABLOCKX,HOLDLOCK)
EXEC(@TableScript)
DROP TABLE dbo.tblFoo;
EXECUTE sp_rename N'dbo.Destination', N'tblFoo', 'OBJECT';
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF XACT_STATE() <> 0 ROLLBACK TRANSACTION;
PRINT ERROR_MESSAGE();
END CATCH;
Проверьте результат.
INSERT INTO dbo.tblFoo (filler,filler2)
OUTPUT inserted.*
VALUES ('foo','bar')
дает
bar filler filler2
----------- --------- ---------
10001 foo bar
Очистка
DROP TABLE dbo.tblFoo
Ответ 2
SQL Server: как установить auto-increment в таблице со строками в нем:
Эта стратегия физически копирует строки примерно в два раза, что может занять гораздо больше времени, если таблица, которую вы копируете, очень велика.
Вы можете сэкономить свои данные, отбросить и перестроить таблицу с помощью автоматического инкремента и первичного ключа, а затем снова загрузить данные.
Я расскажу вам пример:
Шаг 1, создайте таблицу foobar (без первичного ключа или автоматического увеличения):
CREATE TABLE foobar(
id int NOT NULL,
name nchar(100) NOT NULL,
)
Шаг 2, вставьте несколько строк
insert into foobar values(1, 'one');
insert into foobar values(2, 'two');
insert into foobar values(3, 'three');
Шаг 3, скопируйте данные foobar в таблицу temp:
select * into temp_foobar from foobar
Шаг 4, падение таблицы foobar:
drop table foobar;
Шаг 5, заново создайте таблицу с помощью первичного ключа и свойств автоматического увеличения:
CREATE TABLE foobar(
id int primary key IDENTITY(1, 1) NOT NULL,
name nchar(100) NOT NULL,
)
Шаг 6, вставьте ваши данные из таблицы temp обратно в foobar
SET IDENTITY_INSERT temp_foobar ON
INSERT into foobar (id, name) select id, name from temp_foobar;
Шаг 7, отбросьте временную таблицу и проверьте, не работает ли она:
drop table temp_foobar;
select * from foobar;
Вы должны это получить, и когда вы проверяете таблицу foobar, столбец идентификатора является автоматическим приращением 1, а id является первичным ключом:
1 one
2 two
3 three
Ответ 3
Если вы хотите сделать это через дизайнера, вы можете сделать это, следуя инструкциям здесь "Сохранить изменения не разрешено" при изменении существующего столбца на нулевое значение
Ответ 4
Если вы не хотите добавлять новый столбец, и вы можете гарантировать, что ваш текущий столбец int уникален, вы можете выбрать все данные во временную таблицу, отбросить таблицу и воссоздать с указанным столбцом IDENTITY, Затем, используя SET IDENTITY INSERT ON
, вы можете вставить все свои данные во временную таблицу в новую таблицу.
Ответ 5
Да, вы можете. Откройте "Инструменты" > "Дизайнеры" > "Таблица" и "Дизайнеры" и снимите флажок "Предотвращение сохранения изменений, предотвращающих сохранение таблицы".
Ответ 6
Нет, вы не можете добавить параметр автоматического увеличения в существующий столбец с данными, я думаю, что вариант, который вы упомянули, является лучшим.
Посмотрите здесь.