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


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.