Як змінити значення стовпців ідентичності програмно?


160

У мене база даних MS SQL 2005 з таблицею Testзі стовпцем ID. ID- стовпець посвідчення.

У цій таблиці в мене є рядки, і всі вони мають відповідну величину автоматичного збільшення ідентифікації.

Тепер я хотів би змінити кожен ідентифікатор у цій таблиці так:

ID = ID + 1

Але коли я це роблю, я отримую помилку:

Неможливо оновити стовпець "Ідентифікатор".

Я спробував це:

    ALTER TABLE Test NOCHECK CONSTRAINT ALL 
    set identity_insert ID ON

Але це не вирішує проблему.

Мені потрібно встановити ідентичність цього стовпця, але мені також час від часу потрібно змінювати значення. Тож моє питання - як виконати це завдання.

Відповіді:


220

Тобі потрібно

set identity_insert YourTable ON

Потім видаліть рядок і вставте його з іншою ідентичністю.

Після того як ви зробили вставку, не забудьте вимкнути ідентифікатор_встановлення

set identity_insert YourTable OFF

133
налаштування цього буде працювати лише при вставці даних, а не при оновленні. Оператор UPDATE як і раніше не буде.
— Хусейн Рончевич

31
Для оновлення потрібно видалити та повторно вставити. Іншого шляху немає.
— ashes999

1
@MartinSmith ваше рішення здається занадто довгим. Можливість зробити це в два етапи (виключення особи, видалення / вставлення, ввімкнення особи) набагато ефективніше.
— ashes999

3
@ ashes999 Це 4 кроки, а не 2. Моя відповідь - лише один (створити таблицю, переключити, оновити, переключити назад, упустити). Імовірно, ти більше знайомий з цими кроками, щоб вони виглядали менш заплутаними. Оновлення може бути набагато ефективнішим, ніж видалити вставку, коли задіяно багато рядків. Також де ви тримаєте видалені рядки? Якщо #tempтаблиця, яку ви скинете, це ще один крок, який ви тут не рахували.
— Мартін Сміт

40

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

1
Дуже струнка. Вивчайте що-небудь нове (BTW, я тестував це на SQLExpress; незважаючи на SWITCH TO, мабуть, він не використовує розділення). Зауважте, що таблиця повинна точно збігатися (індекси, FK та ін.)
— Марк Совул

1
Чи працює метод перемикання, коли у вас вбудовані ПК, FK, індекс та представлення на оригінальній таблиці? Чи зламаються вони за допомогою цього методу?
— TJ

1
@tj при створенні сценарію таблиці темп виводиться з вихідної таблиці, включаючи всі індекси та обмеження. Потім змініть назви таблиці та обмеження, щоб уникнути зіткнень. Перегляди не спричинять проблем, якщо не буде індексовано чи схематично.
— Мартін Сміт

Не працює, якщо на столі є повнотекстовий індекс пошуку. Я припускаю, що можна його видалити і відтворити після цього, але я не перевіряв.
— youen

26

За допомогою інтерфейсу в менеджері SQL Server 2005 змініть стовпчик, видаліть властивість авточисла (ідентичність) стовпця (виберіть таблицю, клацнувши правою кнопкою миші та виберіть "Дизайн").

Потім запустіть свій запит:

UPDATE table SET Id = Id + 1

Потім перейдіть і додайте властивість autonumber назад до стовпця.


3
Якщо внести зміни вручну, ви можете попросити менеджера створити сценарій SQL для зміни (меню дизайнера таблиць, створити сценарій зміни). Для цієї зміни він створює нову таблицю і копіює дані впоперек, а потім видаляє оригінал.
— Робін Беннетт

2
@tomaszs - Приклад коду, який також є більш ефективним, оскільки він фізично не відновлює таблицю взагалі (це зробило б це двічі), є в моїй пізній відповіді тут
— Мартін Сміт,

Ви не можете додати особу назад. Чи ти? stackoverflow.com/questions/1049210/…
— Томаш Кубес

Дякую. Це було ідеально. У мене був 1 рядок у моїй таблиці, про який я не знав, тож у моїх скриптах завантажувальної програми для моєї таблиці було Idвідключено значення автоматичної ідентичності на 1.
— Шива

18

По-перше, встановлення або відключення IDENTITY_INSERT для цього питання не працюватиме для того, що потрібно (використовується для вставки нових значень, таких як підключення прогалин).

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


9

Це можна зробити за допомогою тимчасової таблиці.

Ідея

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

SQL запити

Скажімо, у вашій testтаблиці є два додаткові стовпці ( column2і column3), а також є дві таблиці з посиланням на зовнішні ключі, що 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;

Це воно.


6

DBCC CHECKIDENT ('databasename.dbo.orders', RESEED, 999) ви можете змінити будь-який номер стовпця ідентичності за допомогою цієї команди, а також ви можете запустити цей номер поля з кожного номера, яке ви хочете. Наприклад, у моїй команді я прошу почати з 1000 (999 + 1) сподіваються, що цього буде достатньо ... удачі


4

Якщо стовпець не є ПК, ви завжди можете створити НОВИЙ стовпець у таблиці із збільшеними номерами, опустіть оригінал та змініть новий на старий.

цікаво, чому вам може знадобитися це зробити ... Більшість, що мені коли-небудь доводилося переробляти зі стовпцями Identity, полягала в тому, щоб заповнити номери, і я щойно в кінці використовував DBCC CHECKIDENT (ім'я таблиці, RESEED, newnextnumber)

Щасти!


1

Модифікація ідентичності може виявитися невдалою залежно від ряду факторів, головним чином обертаючись навколо об'єктів / зв’язків, пов'язаних зі стовпцем ідентифікатора. Здається, що дизайн дизайну є таким же важливим питанням, як ідентифікатор повинен рідко колись змінюватися (я впевнений, що у вас є свої причини і вказуєте на зміни). Якщо вам дійсно потрібно час від часу змінювати ідентифікатори, я б запропонував або створити новий стовпець манекена, який не є первинним ключем / автономером, яким ви можете керувати самостійно та генерувати з поточних значень. Крім того, ідея Chrisotphers, наведена вище, буде моєю іншою пропозицією, якщо у вас виникнуть проблеми із дозволом вставлення особи.

Удачі

PS це не виходить з ладу, тому що послідовний порядок, в якому він працює, намагається оновити значення в списку до елемента, який вже існує в списку ідентифікаторів? зчепившись за соломкою, можливо додайте кількість рядків + 1, тоді, якщо це працює, відніміть кількість рядків: -S


1

Якщо вам потрібно періодично змінювати ідентифікатори, можливо, краще не використовувати стовпчик посвідчення. Раніше ми використовували поля авточислення вручну, використовуючи таблицю "Лічильники", яка відстежує наступний ідентифікатор для кожної таблиці. IIRC ми ​​це зробили, оскільки стовпці ідентифікації спричиняли пошкодження бази даних у SQL2000, але можливість зміни ідентифікаторів іноді була корисною для тестування.


1

Ви можете вставити нові рядки із зміненими значеннями, а потім видалити старі рядки. Наступний приклад зміни ідентифікатора таким же, як іноземний ключ 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

1

Спочатку збережіть усі ідентифікатори та програмуйте їх програмно до значень, яких ви не хочете, потім вийміть їх із бази даних, а потім знову вставте, використовуючи щось подібне:

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вимкнете, ви отримаєте таку помилку:

Неможливо вставити явне значення стовпця особи в таблицю "Тест", коли для IDENTITY_INSERT встановлено значення OFF.


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


1
Не впевнений, що ти справді тут відповів на питання.
— Ендрю Барбер

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.