Utworzyłem tabelę w bazie danych, która już istnieje w innej bazie danych. Początkowo było wypełnione starymi danymi DB. PK tabeli musiało otrzymać wartości, które już istnieją w tych rekordach, więc nie mogło to być automatyczne zwiększenie.
Teraz potrzebuję nowego stołu, aby jego PK było automatycznie zwiększane. Ale jak mogę to zrobić, gdy PK już istnieje i ma dane?
IDENTITY
?Odpowiedzi:
Rozumiem twoje pytanie: masz istniejącą tabelę z kolumną, która do tej pory była wypełniona wartościami ręcznymi, a teraz chcesz (1) ustawić tę kolumnę jako
IDENTITY
kolumnę i (2) upewnić się, żeIDENTITY
początki od najnowszej wartości w istniejących wierszach.Po pierwsze, niektóre dane testowe do zabawy:
Celem jest, aby kolumny klucza podstawowego tabeli, w
id
AnIDENTITY
kolumna, która rozpocznie się o godzinie 21 do następnego rekordu, który zostanie wstawiony. W tym przykładzie kolumnaxyz
reprezentuje wszystkie pozostałe kolumny tabeli.Zanim cokolwiek zrobisz, przeczytaj ostrzeżenia na dole tego postu.
Po pierwsze, na wypadek, gdyby coś poszło nie tak:
Teraz dodajmy tymczasową kolumnę roboczą
id_temp
i ustawmy tę kolumnę na wartości istniejącejid
kolumny:Następnie musimy usunąć istniejącą
id
kolumnę (nie możesz po prostu „dodać”IDENTITY
do istniejącej kolumny, musisz utworzyć kolumnę jakoIDENTITY
). Klucz podstawowy również musi przejść, ponieważ kolumna zależy od niego.... i dodaj kolumnę ponownie, tym razem jako
IDENTITY
, wraz z kluczem podstawowym:Oto, gdzie robi się ciekawie. Możesz włączyć
IDENTITY_INSERT
w tabeli, co oznacza, że możesz ręcznie zdefiniować wartościIDENTITY
kolumny podczas wstawiania nowych wierszy (jednak nie aktualizując istniejących wierszy).Przy takim zestawie
DELETE
wszystkie wiersze w tabeli, ale wiersze, które usuwasz, znajdują sięOUTPUT
bezpośrednio w tej samej tabeli - ale z określonymi wartościami dlaid
kolumny (z kolumny zapasowej).Po zakończeniu
IDENTITY_INSERT
wyłącz ponownie.Usuń tymczasową kolumnę, którą dodaliśmy:
I w końcu ponownie umieściłem
IDENTITY
kolumnę, więc następny rekordid
zostanie wznowiony po najwyższej istniejącej liczbie wid
kolumnie:Sprawdzając przykładową tabelę, najwyższa
id
liczba to 20.Dodaj kolejny wiersz i sprawdź jego nowy
IDENTITY
:W tym przykładzie nowy wiersz będzie miał
id=21
. Wreszcie, jeśli jesteś zadowolony, dokonaj transakcji:Ważny
Nie jest to trywialna operacja i niesie ze sobą całkiem sporo zagrożeń, o których powinieneś wiedzieć.
Zrób to w dedykowanym środowisku testowym. Miej kopie zapasowe. :)
Lubię go używać,
BEGIN/COMMIT TRANSACTION
ponieważ zapobiega bałaganowi innych procesów w tabeli, gdy jesteś w trakcie jej zmieniania, i daje ci możliwość przywrócenia wszystkiego do tyłu, jeśli coś pójdzie nie tak. Jednak każdy inny proces, który próbuje uzyskać dostęp do tabeli przed zatwierdzeniem transakcji, czeka. Może to być dość złe, jeśli masz duży stół i / lub pracujesz w środowisku produkcyjnym.OUTPUT .. INTO
nie będzie działać, jeśli tabela docelowa ma ograniczenia dla klucza obcego lub dowolną z wielu innych funkcji, których nie pamiętam z głowy. Zamiast tego możesz zamiast tego rozładować dane do tabeli tymczasowej, a następnie wstawić je z powrotem do oryginalnej tabeli. Możesz być w stanie używać przełączania partycji (nawet jeśli nie używasz partycji).Uruchom te instrukcje jeden po drugim, a nie jako partia lub procedura składowana.
Spróbuj wymyślić inne rzeczy, które mogą zależeć od
id
upuszczanej i odtwarzanej kolumny. Wszelkie indeksy będą musiały zostać usunięte i ponownie utworzone (tak jak zrobiliśmy to z kluczem podstawowym). Pamiętaj, aby wykonać skrypt każdego indeksu i ograniczenia, które trzeba będzie wcześniej utworzyć.Wyłącz dowolne
INSERT
iDELETE
wyzwalacze na stole.Jeśli ponowne utworzenie tabeli jest opcją:
Jeśli ponowne utworzenie tabeli jest dla Ciebie opcją, wszystko jest o wiele prostsze:
id
kolumny jakoIDENTITY
,IDENTITY_INSERT ON
do stołu,IDENTITY_INSERT OFF
iźródło
IDENTITY_INSERT ON
, wypełnić i wyłączyć. Właśnie to chciałem zrobić, ale nie wiedziałem, że MSSQL to obsługuje.Przenoszenie danych przy użyciu UPDATE, DELETE lub INSERT może zająć sporo czasu i zużyć zasoby (IO) zarówno na pliki danych, jak i pliki / dyski dziennika. Podczas pracy nad dużym stołem można uniknąć zapełniania dziennika transakcji potencjalnie dużą ilością rekordów: przy przełączaniu partycji zmieniane są tylko metadane.
Nie wiąże się to z przenoszeniem danych, dlatego odbywa się to bardzo szybko (niemal natychmiastowo).
Przykładowa tabela
Pytanie nie pokazuje oryginalnej tabeli DDL. Poniższy kod DDL zostanie użyty jako przykład w tej odpowiedzi:
Przy pomocy tego zapytania dodaje się pół tuzina fałszywych identyfikatorów losowych od 0 do 15:
Przykładowe dane w
IdT
Nowy stół z
IDENTITY(0, 1)
Jedynym problemem
idT
jest brakIDENTITY(0, 1)
właściwości na id. Nowa tabela o podobnej strukturze iIDENTITY(0, 1)
utworzona:Oprócz
IDENTITY(0, 1)
,idT_Switch
jest identycznaidT
.Klucz obcy
Włączone klucze obce
idT
muszą zostać usunięte, aby umożliwić użycie tej techniki.Przełącznik partycji
idT
IidT_Switch
tabele mają zgodną strukturę. Zamiast używaćDELETE
,UPDATE
orazINSERT
instrukcje, aby przenieść wiersze odidT
doidT_Switch
lub naidT
sobie,ALTER TABLE ... SWITCH
można stosować:Pojedyncza „partycja”
PK_idT
(całej tabeli) zostaje przeniesiona doPK_idT_Switch
(i odwrotnie).idT
teraz zawiera 0 wierszy iidT_Switch
zawiera 6 wierszy.Pełną listę wymagań dotyczących zgodności źródeł i miejsc docelowych można znaleźć tutaj:
Wydajne przesyłanie danych za pomocą przełączania partycji
Zauważ, że to użycie
SWITCH
nie wymaga Enterprise Edition, ponieważ nie ma wyraźnego podziału na partycje. Niepodzielona na partycje tabela jest uważana za tabelę z pojedynczą partycją począwszy od SQL Server 2005.Zastąpić
idT
idT
jest teraz pusty i bezużyteczny i można go upuścić:idT_Switch
można zmienić nazwę i zastąpi starąidT
tabelę:Klucz obcy
Klucze obce można ponownie dodać do nowej
idT
tabeli. Coś innego, co wcześniej usunięto,idT
aby tabele były kompatybilne do przełączania, również będzie musiało zostać wykonane ponownie.Reseed
Ta komenda zwraca 0. Tabela idT zawiera 6 wierszy z MAX (id) = 15. Można użyć DBCC CHECKIDENT (nazwa_tabeli) :
Ponieważ 15 jest większe niż 0, zostanie ono automatycznie zresetowane bez szukania MAX (id):
IDENT_CURRENT zwraca teraz 15 .
Przetestuj i dodaj dane
Proste
INSERT
stwierdzenie:Dodaje ten wiersz:
id
Kolumna jest teraz za pomocą tożsamości i nowa wartość jest faktycznie 16 (15 + 1).Więcej informacji
Tutaj jest powiązane pytanie i odpowiedź z dodatkowym zapleczem
SWITCH
techniki:Dlaczego usunięcie właściwości Tożsamość w kolumnie nie jest obsługiwane
źródło
Jeśli chcesz zacząć od nowej wartości tożsamości, musisz ponownie wprowadzić swoją tożsamość. Zajrzyj do dokumentacji dla
CHECKIDENT
źródło
WŁĄCZ i WYŁĄCZ IDENTITY_INSERT
Jeśli twoja tabela to TABELA_A, to
źródło