152

Mam bazę danych MS SQL 2005 z tabelą Test z kolumną ID. ID to kolumna tożsamości.Jak programowo zmienić wartości kolumny tożsamości?

Mam wiersze w tej tabeli i wszystkie z nich mają przypisaną wartość autoinkrementacji.

Teraz chciałbym zmienić każdy identyfikator w tej tabeli tak:

ID = ID + 1 

Ale kiedy to zrobić pojawia się błąd:

Cannot update identity column 'ID'. 

próbowałam to:

ALTER TABLE Test NOCHECK CONSTRAINT ALL 
set identity_insert ID ON 

Ale to nie rozwiązuje problemu.

Potrzebuję ustawić tożsamość dla tej kolumny, ale od czasu do czasu muszę również zmieniać wartości. Więc moim pytaniem jest, jak wykonać to zadanie.

Odpowiedz

212

Trzeba

set identity_insert YourTable ON 

Następnie usunąć wiersz i włóż ją z inną tożsamością.

Po wykonaniu wkładka nie zapomnij włączyć IDENTITY_INSERT off

set identity_insert YourTable OFF 
+130

ustawienie to zadziała tylko podczas wstawiania danych, a nie podczas aktualizacji. Instrukcja UPDATE nadal się nie powiedzie. –

+29

Aby zaktualizować, należy usunąć i ponownie wstawić. Nie ma innego wyjścia. – ashes999

+1

@MartinSmith Twoje rozwiązanie wydaje się zbyt długie.Możliwość zrobienia tego w dwóch etapach (wyłączenie tożsamości, usunięcie/wstawienie, włączenie tożsamości) jest znacznie bardziej efektywne. – ashes999

26

Poprzez interfejs użytkownika w menedżerze SQL Server 2005 zmień kolumnę, usuwając właściwość autonumerowania (tożsamości) kolumny (wybierz tabelę, klikając ją prawym przyciskiem myszy i wybierz "Projekt").

Następnie uruchom zapytanie:

UPDATE table SET Id = Id + 1 

następnie przejść i dodać właściwość Autonumerowanie z powrotem do kolumny.

+4

i jak zrobić to z kodu? –

+3

Jeśli wprowadzisz zmianę ręcznie, możesz poprosić menedżera o wygenerowanie skryptu SQL dla zmiany (menu projektanta tabel, wygeneruj skrypt zmiany). W przypadku tej zmiany tworzy nową tabelę i kopiuje dane, a następnie usuwa oryginał. –

+2

@tomaszs - Przykład kodu, który jest również bardziej wydajny, ponieważ nie fizycznie odbudowuje go w ogóle (to zrobiłoby to dwa razy) jest w mojej późnej odpowiedzi [tutaj] (http://stackoverflow.com/a/17249583/ 73226) –

4

Jeśli kolumna nie jest PK, zawsze można utworzyć NOWĄ kolumnę w tabeli z rosnącymi liczbami, upuścić oryginał, a następnie zmienić nowy, aby był stary.

ciekaw, dlaczego może trzeba to zrobić ... najbardziej ja kiedykolwiek miałem futz z kolumnami tożsamość została zasypka do numerów i właśnie skończył przy użyciu DBCC CHECKIDENT (nazwatabeli, RESEED, newnextnumber)

powodzenia!

1

Modyfikowanie tożsamości może się nie udać w zależności od wielu czynników, głównie dotyczących obiektów/relacji powiązanych z kolumną identyfikatora. Wygląda na to, że db design jest tutaj problemem, ponieważ id powinien rzadko, jeśli kiedykolwiek się zmienić (jestem pewien, że masz swoje powody i tłumi zmiany). Jeśli naprawdę musisz zmienić identyfikator od czasu do czasu, proponuję utworzenie nowej fałszywej kolumny identyfikacyjnej, która nie jest kluczem podstawowym/autonumerycznym, którym możesz zarządzać samodzielnie i generować z bieżących wartości. Ewentualnie powyższy pomysł może być moją drugą sugestią, jeśli masz problemy z zezwoleniem na wstawianie tożsamości.

Powodzenia

PS nie jest niepowodzeniem, ponieważ kolejność sekwencyjnego jest uruchomiony w próbuje zaktualizować wartość w liście do elementu, który już istnieje na liście identyfikatorów? trzymając się za słomki, być może dodaj liczbę wierszy + 1, a następnie, jeśli to działa, odejmij liczbę wierszy: -S

18

Po pierwsze ustawienie IDENTITY_INSERT w tym przypadku nie będzie działało zgodnie z wymaganiami (jest to służy do wstawiania nowych wartości, takich jak zatykanie przerw).

Wykonanie operacji za pośrednictwem interfejsu GUI powoduje tylko utworzenie tabeli tymczasowej, skopiowanie wszystkich danych do nowej tabeli bez pola tożsamości i zmianę nazwy tabeli.

1

Jeśli musisz czasami zmieniać identyfikatory, prawdopodobnie lepiej nie używać kolumny tożsamości. W przeszłości ręcznie zaimplementowaliśmy pola autonumerowania za pomocą tabeli "Liczniki", która śledzi następny identyfikator dla każdej tabeli. IIRC zrobiliśmy to, ponieważ kolumny tożsamości powodowały uszkodzenie bazy danych w SQL2000, ale możliwość zmiany identyfikatorów okazjonalnie była przydatna do testowania.

6

DBCC CHECKIDENT ('databasename.dbo.orders', RESEED, 999) można zmieniać dowolną liczbę kolumn tożsamość z tym polecenia, a także możesz uruchomić ten numer pola z każdego numeru, który chcesz. na przykład w moim poleceniu pytam, aby rozpocząć od 1000 (999 + 1) nadzieję, że to wystarczy ... powodzenia

9

Może to zrobić przy użyciu tabeli tymczasowej.

Pomysł

  • wyłączyć ograniczenia (w przypadku, gdy id odwołuje się klucz obcy)
  • utworzyć tabelę temp z nowym identyfikatorem
  • usunąć zawartość tabeli
  • skopiowania danych historycznych z skopiowanego do oryginalnego tabeli tabeli
  • włączaj wstępnie wyłączone więzy

zapytań SQL

powiedzmy tabelę test mają dwie dodatkowe kolumny (column2 i column3) oraz że istnieją 2 tabele zawierające klucze obce przedstawieniu test nazwie foreign_table1 i foreign_table2 (ponieważ kwestie prawdziwym życiu nigdy nie są proste).

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; 

To wszystko.

0

Widziałem dobry artykuł, który pomógł mi w ostatniej chwili .. Próbowałem wstawić kilka wierszy w tabeli, która miała kolumnę tożsamości, ale zrobiła to źle i trzeba usunąć z powrotem. Po usunięciu wierszy moja kolumna tożsamości uległa zmianie. Próbowałem znaleźć sposób na aktualizację kolumny, która została wstawiona, ale - bez powodzenia. Tak więc, podczas poszukiwania w google znalazłem link ..

  1. Usunięto kolumny, która została błędnie wstawione
  2. Używaj wkładki przy użyciu siły tożsamości on/off (wyjaśnione poniżej)

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

Nie jestem pewien, czy naprawdę odpowiedziałeś na pytanie tutaj. –

39

IDENTITY wartości kolumn są niezmienne.

Możliwe jest jednak przełączenie metadanych tabeli w celu usunięcia właściwości IDENTITY, wykonanie aktualizacji, a następnie przełączenie z powrotem.

Zakładając następującą strukturę

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' 

Następnie można zrobić

/*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*/ 

W SQL Server 2012 możliwe jest mieć wzrastających kolumnę auto, które mogą być również zaktualizowany bardziej wprost z 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 dla gładkiej odpowiedzi i informacji o sekwencjach w SQL Server 2012. –

+1

Bardzo śliski. Naucz się czegoś nowego każdego dnia (BTW testowałem to na SQLExpress, pomimo tego, że SWITCH TO nie używa partycji, widocznie). Zwróć uwagę, że tabela musi dokładnie pasować do siebie (indeksy, FK itp.). –

+0

Czy metoda przełączania działa, gdy masz PK, FK, indeks i widoki zbudowane na oryginalnej tabeli? Czy złamią się przy użyciu tej metody? –

1

Możesz wstawić nowe wiersze z modem ified wartości, a następnie usuń stare wiersze. Poniższy przykład zmiany identyfikatora być taki sam jak klucz obcy 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

Bardzo ładny pytanie, najpierw musimy na IDENTITY_INSERT dla określonej tabeli, po czym uruchomić zapytanie INSERT (Należy podać nazwę kolumny).

Uwaga: Po edycji kolumna tożsamości, nie zapomnij off IDENTITY_INSERT. Jeśli tego nie zrobisz, nie możesz edytować kolumny tożsamości dla żadnej innej tabeli.

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

Najpierw zapisać wszystkie identyfikatory i zmieniać je programowo do wartości wy wa, a następnie usunąć je z bazy danych, a następnie włóż je ponownie, używając coś podobnego:

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

Dla użycie wkładki zbiorczej:

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 

Przykładowe dane z file.csv:

2; 
3; 
4; 
5; 
6; 

Jeśli nie ustawić identity_insert aby wyłączyć otrzymasz następujący błąd:

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

Powiązane problemy