W SQLite, AUTOINCREMENT
kolumna to taka, która używa automatycznie zwiększanej wartości dla każdego wiersza wstawionego do tabeli.
Istnieje kilka sposobów na utworzenie AUTOINCREMENT
kolumna:
- Możesz go utworzyć niejawnie, gdy zdefiniujesz kolumnę jako
INTEGER PRIMARY KEY
. - Możesz go utworzyć jawnie za pomocą
AUTOINCREMENT
słowo kluczowe. Jedną z wad tej metody jest to, że wykorzystuje dodatkowy procesor, pamięć, miejsce na dysku i obciążenie we/wy dysku.
Obie metody powodują, że kolumna używa zwiększanej wartości za każdym razem, gdy nowy wiersz jest wstawiany z NULL
w tej kolumnie.
Istnieją jednak pewne subtelne różnice między sposobem działania każdej metody.
Bez słowa kluczowego AUTOINCREMENT
Kiedy deklarujesz kolumnę jako INTEGER PRIMARY KEY
, automatycznie się zwiększy. Dlatego tak naprawdę nie musisz używać AUTOINCREMENT
słowo kluczowe, aby mieć kolumnę, która używa automatycznie rosnącej wartości dla każdego wiersza.
Gdy to zrobisz, każdy NULL
wartości są konwertowane na bieżący ROWID
. Innymi słowy, jeśli wstawisz NULL
do tej kolumny, zostanie przekonwertowany na bieżący ROWID
.
W rzeczywistości działa to tak, że kolumna staje się aliasem dla ROWID
. Możesz uzyskać dostęp do ROWID
wartość przy użyciu dowolnej z czterech nazw; nazwa kolumny, ROWID
, _ROWID_
lub OID
.
Jedna korzyść z pominięcia AUTOINCREMENT
słowo kluczowe to zmniejszenie procesora, pamięci, miejsca na dysku i narzutu we/wy dysku.
Ważną wadą jest jednak to, że nie możesz zagwarantować, że wszystkie wiersze zostaną powiększone w kolejności rosnącej. Wynika to ze sposobu, w jaki działa automatyczne zwiększanie przy pominięciu AUTOINCREMENT
słowo kluczowe a użycie tego słowa kluczowego.
Gdy pominiesz AUTOINCREMENT
słowo kluczowe, raz ROWID
jest równa największej możliwej liczbie całkowitej (9223372036854775807), SQLite spróbuje znaleźć nieużywany dodatni ROWID
losowo.
Jednak tak długo, jak nigdy nie użyjesz maksymalnego ROWID
wartości i nigdy nie usuwasz wpisu w tabeli z największym ROWID
, ta metoda wygeneruje monotonicznie rosnący unikalny ROWID
s.
Za pomocą słowa kluczowego AUTOINCREMENT
Możesz również jawnie utworzyć kolumny z automatycznym przyrostem. Aby to zrobić, użyj AUTOINCREMENT
słowo kluczowe.
Gdy używasz tej metody, do określenia wartości autoinkrementacji używany jest nieco inny algorytm.
Kiedy używasz AUTOINCREMENT
słowo kluczowe, ROWID
wybrany dla nowego wiersza jest co najmniej o jeden większy niż największy ROWID
który kiedykolwiek wcześniej istniał w tej samej tabeli.
Innymi słowy, nie wróci i nie użyje ponownie usuniętych wcześniej ROWID
wartości. Po największym możliwym ROWID
został wstawiony, nowe wstawki nie są dozwolone. Każda próba wstawienia nowego wiersza zakończy się niepowodzeniem z SQLITE_FULL
błąd.
Dlatego użycie tej metody gwarantuje, że ROWID
s rosną monotonicznie. Innymi słowy, możesz polegać na tej metodzie, aby mieć ROWID
s w porządku rosnącym.
Nie oznacza to jednak, że wartości zawsze będą się zwiększać o 1. Oznacza to po prostu, że nigdy się nie zmniejszą.
Przykład
Oto przykład pokazujący różnicę między niejawnym i jawnym definiowaniem kolumny auto-inkrementacji.
CREATE TABLE Cats(
CatId INTEGER PRIMARY KEY,
CatName
);
CREATE TABLE Dogs(
DogId INTEGER PRIMARY KEY AUTOINCREMENT,
DogName
);
INSERT INTO Cats VALUES
( NULL, 'Brush' ),
( NULL, 'Scarcat' ),
( NULL, 'Flutter' );
INSERT INTO Dogs VALUES
( NULL, 'Yelp' ),
( NULL, 'Woofer' ),
( NULL, 'Fluff' );
SELECT * FROM Cats;
SELECT * FROM Dogs;
Początkowy wynik:
CatId CatName ---------- ---------- 1 Brush 2 Scarcat 3 Flutter DogId DogName ---------- ---------- 1 Yelp 2 Woofer 3 Fluff
Teraz usuńmy ostatni wiersz w każdej tabeli, wstawmy je ponownie, a następnie wybierzmy wynik:
DELETE FROM Cats WHERE CatId = 3;
DELETE FROM Dogs WHERE DogId = 3;
INSERT INTO Cats VALUES ( NULL, 'New Flutter' );
INSERT INTO Dogs VALUES ( NULL, 'New Fluff' );
SELECT * FROM Cats;
SELECT * FROM Dogs;
Wynik:
CatId CatName ---------- ---------- 1 Brush 2 Scarcat 3 New Flutter DogId DogName ---------- ---------- 1 Yelp 2 Woofer 4 New Fluff
Podsumowując, Koty tabela została utworzona bez AUTOINCREMENT
słowo kluczowe i Psy tabela została utworzona z AUTOINCREMENT
słowo kluczowe.
Po usunięciu ostatniego wiersza z Koty tabela, następna INSERT
operacja spowodowała ten sam ROWID
zostanie ponownie wykorzystana w tym rzędzie.
Jednak Psy stół był inny. Został utworzony za pomocą AUTOINCREMENT
słowo kluczowe i dlatego nie może ponownie użyć poprzedniej wartości. Po prostu zwiększa się do następnej wartości, pozostawiając lukę w numeracji.
Maksymalny ROWID
Możemy pójść o krok dalej w poprzednim przykładzie i wstawić nowy wiersz, jawnie używając maksymalnego ROWID
możliwe.
INSERT INTO Cats VALUES ( 9223372036854775807, 'Magnus' );
INSERT INTO Dogs VALUES ( 9223372036854775807, 'Maximus' );
SELECT * FROM Cats;
SELECT * FROM Dogs;
Wynik:
CatId CatName -------------------- -------------------- 1 Brush 2 Scarcat 3 New Flutter 9223372036854775807 Magnus DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 9223372036854775807 Maximus
OK, więc obie tabele używają największej możliwej liczby całkowitej jako największego ROWID
wartości.
Zobaczmy, co się stanie, gdy spróbuję wstawić nowy wiersz do każdej tabeli (bez jawnego określania wartości dla automatycznie zwiększanych kolumn).
Wstaw do Koty tabela:
INSERT INTO Cats VALUES ( NULL, 'Scratchy' );
SELECT * FROM Cats;
Wynik:
CatId CatName -------------------- -------------------- 1 Brush 2 Scarcat 3 New Flutter 267244677462397326 Scratchy 9223372036854775807 Magnus
Więc Koty stół zakończył się sukcesem. Zauważ jednak, że nowa wartość auto-inkrementacji jest mniejsza niż poprzednia (nie ma innej opcji).
Nie mając żadnej innej kolumny do zapisania daty/godziny wstawienia/zaktualizowania wiersza, można błędnie założyć, że Magnus został wstawiony po Scratchy .
Teraz spróbujmy wstawić nowy wiersz do Psów tabela:
INSERT INTO Dogs VALUES ( NULL, 'Lickable' );
Wynik:
Error: database or disk is full
Więc otrzymujemy inny wynik niż Koty tabela.
Otrzymuję ten błąd, ponieważ największy możliwy ROWID
jest już używany w tabeli, a ponieważ ta tabela została utworzona za pomocą AUTOINCREMENT
słowo kluczowe, nie wróci i nie wyszuka nieużywanego ROWID
wartość.
SELECT * FROM Dogs;
Wynik:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 9223372036854775807 Maximus
Co więcej, nadal będę otrzymywał ten błąd, nawet jeśli usunę Maximus z tabeli (np. pies z maksymalnym ROWID
wartość).
Spróbujmy:
DELETE FROM Dogs WHERE DogId = 9223372036854775807;
INSERT INTO Dogs VALUES ( NULL, 'Lickable' );
Wynik:
Error: database or disk is full
Więc nie tylko pojawia się błąd, ale także usunąłem Maximus :
SELECT * FROM Dogs;
Wynik:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff
Należy pamiętać, że stanie się to nawet po zmianie ROWID
wartość na niższą wartość. Fakt, że użyłem już ROWID 9223372036854775807 oznacza, że AUTOINCREMENT
nie będzie już zwiększać się automatycznie.
Dzieje się tak, ponieważ AUTOINCREMENT
używa tylko wartości, które są co najmniej o jeden wyższe niż jakakolwiek wartość, która kiedykolwiek istniała w tej samej tabeli .
Od teraz, gdybym chciał nadal wstawiać wartości do tej kolumny, musiałbym jawnie wstawić wartość. Zakłada się, że nie mam już 9223372036854775807 wierszy w tabeli.
Wstawmy ponownie Maximus z niższym ROWID
i spróbuj ponownie:
INSERT INTO Dogs VALUES ( 5, 'Maximus' );
SELECT * FROM Dogs;
Wynik:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 5 Maximus
Teraz spróbujmy wstawić Lickable jeszcze raz, używając AUTOINCREMENT
:
INSERT INTO Dogs VALUES ( NULL, 'Lickable' );
Wynik:
Error: database or disk is full
Więc nawet jeśli usunąłem wiersz zawierający maksymalny ROWID
wartość 9223372036854775807, to nadal uniemożliwia mi automatyczne zwiększanie kolumny.
Dokładnie tak to zostało zaprojektowane. Maksymalny ROWID
był wcześniej w tej tabeli, więc AUTOINCREMENT
nie zwiększy się automatycznie ponownie w tej tabeli.
Jedynym sposobem dodania nowego wiersza do tej tabeli jest ręczne wstawienie ROWID
wartość.
INSERT INTO Dogs VALUES (6, 'Lickable');
SELECT * FROM Dogs;
Wynik:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 5 Maximus 6 Lickable