SQL Server, как установить автоинкремент после создания таблицы без потери данных? - PullRequest
47 голосов
/ 22 мая 2011

У меня есть таблица table1 в SQL Server 2008, и в ней есть записи.

Я хочу, чтобы столбец первичного ключа table1_Sno был столбцом с автоинкрементом. Можно ли это сделать без какой-либо передачи данных или клонирования таблицы?

Я знаю, что могу использовать ALTER TABLE для добавления столбца с автоинкрементом, но могу ли я просто добавить параметр AUTO_INCREMENT в существующий столбец, который является первичным ключом?

Ответы [ 7 ]

64 голосов
/ 22 мая 2011

Изменение свойства IDENTITY действительно является изменением только метаданных.Но для непосредственного обновления метаданных требуется запуск экземпляра в однопользовательском режиме и возиться с некоторыми столбцами в sys.syscolpars, и он недокументирован / не поддерживается, и я не рекомендовал бы или предоставлю какие-либо дополнительные сведения.

ДляЛюди, которые сталкивались с этим ответом на SQL Server 2012+, безусловно, самым простым способом достижения этого результата в автоинкрементном столбце было бы создать объект SEQUENCE и установить next value for seq в качестве столбца по умолчанию.

В качестве альтернативы или для предыдущих версий (начиная с 2005 года), решение, опубликованное на этом элементе соединения , демонстрирует полностью поддерживаемый способ сделать это без необходимости в размере операций с данными с использованием ALTER TABLE...SWITCH.Также в блоге о 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
4 голосов
/ 08 апреля 2014

SQL Server: Как установить автоинкремент для таблицы со строками в ней:

Эта стратегия физически копирует строки дважды, что может занять гораздо больше времени, если копируемая таблица очень велика,

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

Я расскажу вам пример:

Шаг 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 во временную таблицу:

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, вставьте свои данные из временной таблицыобратно в 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, а идентификатор является первичным ключом:

1    one
2    two
3    three
3 голосов
/ 22 августа 2015

Если вы хотите сделать это через конструктор, вы можете сделать это, следуя приведенным здесь инструкциям «Сохранить изменения не разрешено» при изменении существующего столбца на обнуляемое

2 голосов
/ 16 августа 2014

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

2 голосов
/ 22 мая 2011

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

1 голос
/ 22 мая 2011

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

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

0 голосов
/ 29 сентября 2018

Нижеприведенный скрипт может быть хорошим решением. Работает и с большими данными.

ALTER DATABASE WMlive УСТАНОВИТЕ ВОССТАНОВЛЕНИЕ ПРОСТОЕ С NO_WAIT

ALTER TABLE WMBOMTABLE DROP CONSTRAINT PK_WMBomTable

ALTER TABLE WMBOMTABLE отбрасываемый столбец BOMID

ALTER TABLE WMBOMTABLE ADD BomID int IDENTITY (1, 1) НЕ ПУСТО;1012 *

ALTER DATABASE WMlive SET ВОССТАНОВЛЕНИЕ ПОЛНОСТЬЮ С NO_WAIT

...