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

Ответ 4

Если вы не хотите добавлять новый столбец, и вы можете гарантировать, что ваш текущий столбец int уникален, вы можете выбрать все данные во временную таблицу, отбросить таблицу и воссоздать с указанным столбцом IDENTITY, Затем, используя SET IDENTITY INSERT ON, вы можете вставить все свои данные во временную таблицу в новую таблицу.

Ответ 5

Да, вы можете. Откройте "Инструменты" > "Дизайнеры" > "Таблица" и "Дизайнеры" и снимите флажок "Предотвращение сохранения изменений, предотвращающих сохранение таблицы".

Ответ 6

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

Посмотрите здесь.