152

У меня есть база данных MS SQL 2005 с таблицей Test с колонкой ID. ID - это столбец идентичности.Как изменить значения столбца идентификатора программным путем?

У меня есть строки в этой таблице, и все они имеют соответствующее значение автоинкрементного ID.

Теперь я хотел бы изменить каждый идентификатор в этой таблице, как это:

ID = ID + 1 

Но когда я делаю это я получаю сообщение об ошибке:

Cannot update identity column 'ID'. 

Я попытался это:

ALTER TABLE Test NOCHECK CONSTRAINT ALL 
set identity_insert ID ON 

Но это не решит проблему.

Мне нужно установить идентификатор в этот столбец, но мне также нужно время от времени менять значения. Поэтому мой вопрос заключается в том, как выполнить эту задачу.

ответ

212

Вы должны

set identity_insert YourTable ON 

Затем удалите строку и вставьте его с другим именем.

После того, как вы сделали вставки не забудьте включить IDENTITY_INSERT от

set identity_insert YourTable OFF 
+130

. Настройка будет работать только при вставке данных, а не при обновлении. Инструкция UPDATE все равно не удастся. –

+29

Для обновления вам необходимо удалить и повторно вставить. Другого пути нет. – ashes999

+1

@MartinSmith ваше решение кажется слишком длинным.Возможность сделать это в два этапа (идентификация, удаление/вставка, идентификация) намного эффективнее. – ashes999

26

С помощью пользовательского интерфейса в менеджере SQL Server 2005 измените столбец, чтобы удалить свойство autonumber (identity) столбца (выберите таблицу, щелкнув правой кнопкой мыши по нему и выберите «Дизайн»).

Затем запустите запрос:

UPDATE table SET Id = Id + 1 

Затем пойти и добавить свойство Autonumber обратно в колонну.

+4

А как это сделать из кода? –

+3

Если вы внесете изменения вручную, вы можете попросить менеджера создать сценарий SQL для изменения (меню конструктора таблиц, сгенерировать скрипт изменений). Для этого изменения он создает новую таблицу и копирует данные, а затем удаляет оригинал. –

+2

@tomaszs - пример кода, который также более эффективен, так как он физически не перестраивает таблицу вообще (это будет делать это дважды) в моем последнем ответе [здесь] (http://stackoverflow.com/a/17249583/ 73226) –

4

Если столбец не является ПК, вы всегда можете создать столбец NEW в таблице с добавочными номерами, отбросить оригинал, а затем изменить новый, чтобы он был старым.

любопытно, почему вам может понадобиться, чтобы сделать это ... самое я когда-либо приходилось futz с колоннами Идентичность засыпки номера, и я просто в конечном итоге с помощью DBCC CHECKIDENT (имя_таблицы, переустановку, newnextnumber)

удачи!

1

Модификация идентификатора может завершиться неудачно в зависимости от ряда факторов, в основном вращающихся вокруг объектов/отношений, связанных с столбцом идентификаторов. Похоже, что дизайн db является проблемой здесь, так как id должен редко когда-либо меняться (я уверен, что у вас есть свои причины и каскадирование изменений). Если вам действительно нужно время от времени менять идентификатор, я бы предложил создать новый столбец id, который не является основным ключом/автономенем, который вы можете управлять собой и генерировать из текущих значений. В качестве альтернативы, идея Chrisotphers, приведенная выше, будет моим другим предложением, если у вас возникнут проблемы с возможностью вставки идентификатора.

Успехов

PS это не подведет, потому что последовательный порядок он работает в пытается обновить значение в списке элемента, который уже существует в списке идентификаторов? сжимая на соломинках, возможно, добавьте количество строк + 1, затем, если это работает, вычтите количество строк: -S

18

Во-первых, установка IDENTITY_INSERT в этом случае не будет работать для того, что вам нужно (это используется для вставки новых значений, например, для запирания зазоров).

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

1

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

6

DBCC CHECKIDENT («databasename.dbo.orders», переустановка, 999) вы можете изменить любое количество столбцов идентичности с этим команду, а также вы можете запустить этот номер поля с каждого номера, которое вы хотите. Например, в моей команде я прошу начать с 1000 (999 + 1) надеюсь, что этого будет достаточно ... удачи

9

Это может выполняется с использованием временной таблицы.

Идея

  • отключить ограничения (в случае, если ваш идентификатор ссылается внешний ключ)
  • создать временную таблицу с новым идентификатором
  • удалить содержимое таблицы
  • скопировать данные обратно из скопированного стола в исходный стол
  • включить запрещенные ограничения

SQL запросов

Допустим, ваш test стол две дополнительные колонки (column2 и column3) и что есть 2 таблицы, имеющие внешние ключи ссылки test под названием foreign_table1 и foreign_table2 (потому что проблемы реальной жизни никогда не просто).

alter table test nocheck constraint all; 
alter table foreign_table1 nocheck constraint all; 
alter table foreign_table2 nocheck constraint all; 
set identity_insert test on; 

select id + 1 as id, column2, column3 into test_copy from test v; 
delete from test; 
insert into test(id, column2, column3) 
select id, column2, column3 from test_copy 

alter table test check constraint all; 
alter table foreign_table1 check constraint all; 
alter table foreign_table2 check constraint all; 
set identity_insert test off; 
drop table test_copy; 

Всё.

0

Я увидел хорошую статью, которая помогла мне в последний момент .. Я пытался вставить несколько строк в таблицу, в которой был столбец с идентификатором, но сделал это неправильно и нужно удалить обратно. Как только я удалил строки, мой столбец идентичности был изменен. Я пытался найти способ обновить столбец, который был вставлен, но не повезло. Таким образом, при поиске на Google нашел ссылку ..

  1. Удаленные столбцы, которые ошибочно вставленные
  2. Использование силы вставки с использованием идентичности вкл/выкл (описано ниже)

http://beyondrelational.com/modules/2/blogs/28/posts/10337/sql-server-how-do-i-insert-an-explicit-value-into-an-identity-column-how-do-i-update-the-value-of-an.aspx

+0

Не уверен, что вы действительно ответили на этот вопрос. –

39

IDENTITY Значения столбцов неизменяемы.

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

Предполагая следующую структуру

CREATE TABLE Test 
(
ID INT IDENTITY(1,1) PRIMARY KEY, 
X VARCHAR(10) 
) 

INSERT INTO Test 
OUTPUT INSERTED.* 
SELECT 'Foo' UNION ALL 
SELECT 'Bar' UNION ALL 
SELECT 'Baz' 

Затем вы можете сделать

/*Define table with same structure but no IDENTITY*/ 
CREATE TABLE Temp 
(
ID INT PRIMARY KEY, 
X VARCHAR(10) 
) 

/*Switch table metadata to new structure*/ 
ALTER TABLE Test SWITCH TO Temp; 

/*Do the update*/ 
UPDATE Temp SET ID = ID + 1; 

/*Switch table metadata back*/ 
ALTER TABLE Temp SWITCH TO Test; 

/*ID values have been updated*/ 
SELECT * 
FROM Test 

/*Safety check in case error in preceding step*/ 
IF NOT EXISTS(SELECT * FROM Temp) 
    DROP TABLE Temp /*Drop obsolete table*/ 

В SQL Server 2012 можно иметь увеличивающийся столбец авто, который также может быть обновлен более прямолинеен с SEQUENCES

CREATE SEQUENCE Seq 
    AS INT 
    START WITH 1 
    INCREMENT BY 1 

CREATE TABLE Test2 
(
ID INT DEFAULT NEXT VALUE FOR Seq NOT NULL PRIMARY KEY, 
X VARCHAR(10) 
) 

INSERT INTO Test2(X) 
SELECT 'Foo' UNION ALL 
SELECT 'Bar' UNION ALL 
SELECT 'Baz' 

UPDATE Test2 SET ID+=1 
+0

+1 для гладкого ответа и информации о последовательностях в SQL Server 2012. –

+1

Очень гладкий. Каждый день узнавайте что-то новое (BTW я тестировал это на SQLExpress, несмотря на то, что SWITCH TO не использует разделение, по-видимому). Обратите внимание, что таблица должна точно соответствовать точно (индексы, FK и т. Д.). –

+0

Используется ли метод switch, когда у вас есть ПК, FK, индекс и представления, построенные на исходной таблице? Будут ли они разбиты, используя этот метод? –

1

Вы можете вставить новые строки с модулем ified, а затем удалите старые строки. Следующий пример изменения идентификатора такой же, как внешний ключ PersonId

SET IDENTITY_INSERT [PersonApiLogin] ON 

INSERT INTO [PersonApiLogin](
     [Id] 
     ,[PersonId] 
     ,[ApiId] 
     ,[Hash] 
     ,[Password] 
     ,[SoftwareKey] 
     ,[LoggedIn] 
     ,[LastAccess]) 
SELECT [PersonId] 
     ,[PersonId] 
     ,[ApiId] 
     ,[Hash] 
     ,[Password] 
     ,[SoftwareKey] 
     ,[LoggedIn] 
     ,[LastAccess] 
FROM [db304].[dbo].[PersonApiLogin] 
GO 

DELETE FROM [PersonApiLogin] 
WHERE [PersonId] <> ID 
GO 
SET IDENTITY_INSERT [PersonApiLogin] OFF 
GO 
0

Очень хороший вопрос, сначала нужно на IDENTITY_INSERT для конкретной таблицы, после чего выполнить запрос вставки (Необходимо указать имя столбца).

Примечание: После редактирования столбца идентичности, не забудьте от IDENTITY_INSERT. Если вы этого не сделали, вы не сможете редактировать столбец идентификатора для любой другой таблицы.

SET IDENTITY_INSERT Emp_tb_gb_Menu ON 
    INSERT Emp_tb_gb_Menu(MenuID) VALUES (68) 
SET IDENTITY_INSERT Emp_tb_gb_Menu OFF 

http://allinworld99.blogspot.com/2016/07/how-to-edit-identity-field-in-sql.html

1

Сначала сохраните все идентификаторы и изменить их программно значения, которые вы wan't, а затем удалить их из базы данных, а затем вставить их снова использовать что-то подобное:

use [Name.Database] 
go 
set identity_insert [Test] ON 
insert into [dbo].[Test] 
      ([Id]) 
    VALUES 
      (2) 
set identity_insert [Test] OFF 

Для объемная вставка:

use [Name.Database] 
go 
set identity_insert [Test] ON 
BULK INSERT [Test] 
FROM 'C:\Users\Oscar\file.csv' 
WITH (FIELDTERMINATOR = ';', 
     ROWTERMINATOR = '\n', 
     KEEPIDENTITY) 
set identity_insert [Test] OFF 

Образец данных из файла file.csv:

2; 
3; 
4; 
5; 
6; 

Если вы не установите identity_insert кремовый вы получите следующее сообщение об ошибке:

Cannot insert explicit value for identity column in table 'Test' when IDENTITY_INSERT is set to OFF.