In SQLite ein AUTOINCREMENT
Spalte verwendet einen automatisch inkrementierten Wert für jede Zeile, die in die Tabelle eingefügt wird.
Es gibt mehrere Möglichkeiten, ein AUTOINCREMENT
zu erstellen Spalte:
- Sie können es implizit erstellen, wenn Sie die Spalte als
INTEGER PRIMARY KEY
definieren . - Sie können es explizit mit dem
AUTOINCREMENT
erstellen Stichwort. Ein Nachteil dieser Methode ist, dass sie zusätzlichen CPU-, Arbeitsspeicher-, Festplattenspeicher- und Festplatten-E/A-Overhead verbraucht.
Beide Methoden bewirken, dass die Spalte jedes Mal einen inkrementierenden Wert verwendet, wenn eine neue Zeile mit NULL
eingefügt wird in dieser Spalte.
Es gibt jedoch einige subtile Unterschiede zwischen der Funktionsweise der einzelnen Methoden.
Ohne das Schlüsselwort AUTOINCREMENT
Wenn Sie eine Spalte als INTEGER PRIMARY KEY
deklarieren , wird es automatisch erhöht. Daher müssen Sie das AUTOINCREMENT
eigentlich nicht verwenden Schlüsselwort, um eine Spalte zu haben, die einen automatisch inkrementierenden Wert für jede Zeile verwendet.
Wenn Sie dies tun, wird jeder NULL
Werte werden in die aktuelle ROWID
konvertiert . Mit anderen Worten, wenn Sie NULL
einfügen in diese Spalte, wird sie in die aktuelle ROWID
konvertiert .
Tatsächlich funktioniert es so, dass die Spalte ein Alias für die ROWID
wird . Sie können auf die ROWID
zugreifen Wert, indem Sie einen von vier Namen verwenden; der Spaltenname, ROWID
, _ROWID_
, oder OID
.
Ein Vorteil des Weglassens des AUTOINCREMENT
Das Schlüsselwort ist, dass es CPU-, Arbeitsspeicher-, Festplattenspeicher- und Festplatten-E/A-Overhead reduziert.
Ein wichtiger Nachteil ist jedoch, dass Sie nicht garantieren können, dass alle Zeilen in aufsteigender Reihenfolge inkrementiert werden. Dies liegt an der Art und Weise, wie die automatische Inkrementierung funktioniert, wenn das AUTOINCREMENT
weggelassen wird Schlüsselwort im Vergleich zur Verwendung dieses Schlüsselworts.
Wenn Sie AUTOINCREMENT
weglassen Stichwort, einmal ROWID
gleich der größtmöglichen ganzen Zahl (9223372036854775807) ist, versucht SQLite, eine unbenutzte positive ROWID
zu finden zufällig.
Allerdings, solange Sie niemals die maximale ROWID
verwenden Wert und Sie löschen nie den Eintrag in der Tabelle mit der größten ROWID
, generiert diese Methode eine monoton ansteigende eindeutige ROWID
s.
Mit dem Schlüsselwort AUTOINCREMENT
Sie können auch explizit automatisch inkrementierende Spalten erstellen. Verwenden Sie dazu das AUTOINCREMENT
Stichwort.
Wenn Sie diese Methode verwenden, wird ein etwas anderer Algorithmus verwendet, um den automatisch inkrementierten Wert zu bestimmen.
Wenn Sie das AUTOINCREMENT
verwenden Schlüsselwort, die ROWID
Die für die neue Zeile gewählte Zahl ist mindestens um eins größer als die größte ROWID
das hat immer zuvor in derselben Tabelle existierte.
Mit anderen Worten, es wird nicht zurückgehen und zuvor gelöschte ROWID
wiederverwenden Werte. Einmal die größtmögliche ROWID
eingefügt wurde, sind keine neuen Einfügungen zulässig. Jeder Versuch, eine neue Zeile einzufügen, schlägt mit einem SQLITE_FULL
fehl Fehler.
Daher garantiert die Verwendung dieser Methode, dass die ROWID
s sind monoton steigend. Mit anderen Worten, Sie können sich auf diese Methode verlassen, um ROWID
zu haben s in aufsteigender Reihenfolge.
Dies bedeutet jedoch nicht, dass die Werte immer um 1 erhöht werden. Es bedeutet nur, dass sie niemals abnehmen werden.
Beispiel
Hier ist ein Beispiel, um den Unterschied zwischen der impliziten und der expliziten Definition einer Auto-Increment-Spalte zu demonstrieren.
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;
Erstes Ergebnis:
CatId CatName ---------- ---------- 1 Brush 2 Scarcat 3 Flutter DogId DogName ---------- ---------- 1 Yelp 2 Woofer 3 Fluff
Lassen Sie uns nun die letzte Zeile in jeder Tabelle löschen, die Zeilen erneut einfügen und dann das Ergebnis auswählen:
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;
Ergebnis:
CatId CatName ---------- ---------- 1 Brush 2 Scarcat 3 New Flutter DogId DogName ---------- ---------- 1 Yelp 2 Woofer 4 New Fluff
Um es noch einmal zusammenzufassen:die Katzen Tabelle wurde ohne erstellt das AUTOINCREMENT
Schlüsselwort und die Hunde Tabelle wurde mit erstellt das AUTOINCREMENT
Schlüsselwort.
Nach dem Löschen der letzten Zeile aus den Cats Tabelle, das nächste INSERT
Der Vorgang führte zu derselben ROWID
für diese Zeile wiederverwendet wird.
Aber die Hunde Tisch war anders. Es wurde mit dem AUTOINCREMENT
erstellt Schlüsselwort und kann daher den vorherigen Wert nicht wiederverwenden. Es wird einfach zum nächsten Wert hochgezählt, wobei eine Lücke in der Nummerierung bleibt.
Maximale ROWID
Wir können das vorherige Beispiel noch einen Schritt weiterführen und eine neue Zeile einfügen, indem wir explizit die maximale ROWID
verwenden möglich.
INSERT INTO Cats VALUES ( 9223372036854775807, 'Magnus' );
INSERT INTO Dogs VALUES ( 9223372036854775807, 'Maximus' );
SELECT * FROM Cats;
SELECT * FROM Dogs;
Ergebnis:
CatId CatName -------------------- -------------------- 1 Brush 2 Scarcat 3 New Flutter 9223372036854775807 Magnus DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 9223372036854775807 Maximus
OK, also verwenden beide Tabellen die größtmögliche Ganzzahl als ihre größte ROWID
Werte.
Mal sehen, was passiert, wenn ich versuche, eine neue Zeile in jede Tabelle einzufügen (ohne explizit einen Wert für die automatisch inkrementierenden Spalten anzugeben).
In die Katzen einfügen Tabelle:
INSERT INTO Cats VALUES ( NULL, 'Scratchy' );
SELECT * FROM Cats;
Ergebnis:
CatId CatName -------------------- -------------------- 1 Brush 2 Scarcat 3 New Flutter 267244677462397326 Scratchy 9223372036854775807 Magnus
Also die Katzen Tabelle war erfolgreich. Beachten Sie jedoch, dass der neue automatisch inkrementierende Wert niedriger ist als der vorherige Wert (es gibt keine andere Option).
Ohne eine andere Spalte zum Aufzeichnen des Datums/der Uhrzeit, zu der die Zeile eingefügt/aktualisiert wurde, könnte man fälschlicherweise annehmen, dass Magnus wurde nach Scratchy eingefügt .
Versuchen wir nun, eine neue Zeile zu den Dogs einzufügen Tabelle:
INSERT INTO Dogs VALUES ( NULL, 'Lickable' );
Ergebnis:
Error: database or disk is full
Wir erhalten also ein anderes Ergebnis als bei den Cats Tabelle.
Ich habe diesen Fehler bekommen, weil die größtmögliche ROWID
bereits in der Tabelle verwendet wird, und weil diese Tabelle mit dem AUTOINCREMENT
erstellt wurde Schlüsselwort, es wird nicht zurückgehen und nach einer unbenutzten ROWID
suchen Wert.
SELECT * FROM Dogs;
Ergebnis:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 9223372036854775807 Maximus
Außerdem bekomme ich diesen Fehler weiterhin, auch wenn ich Maximus lösche aus der Tabelle (also der Hund mit der höchsten ROWID
). Wert).
Versuchen wir es:
DELETE FROM Dogs WHERE DogId = 9223372036854775807;
INSERT INTO Dogs VALUES ( NULL, 'Lickable' );
Ergebnis:
Error: database or disk is full
Wir bekommen also nicht nur einen Fehler, sondern ich habe auch Maximus gelöscht :
SELECT * FROM Dogs;
Ergebnis:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff
Es ist wichtig zu beachten, dass dies auch dann geschieht, wenn ich die ROWID
ändere Wert auf einen niedrigeren Wert. Die Tatsache, dass ich bereits eine ROWID von 9223372036854775807 verwendet habe, bedeutet, dass AUTOINCREMENT
wird nicht mehr automatisch hochgezählt.
Das liegt daran, dass AUTOINCREMENT
verwendet nur Werte, die mindestens um eins höher sind als alle Werte, die jemals zuvor in derselben Tabelle existierten .
Wenn ich von nun an weiterhin Werte in diese Spalte einfügen wollte, müsste ich den Wert explizit einfügen. Dies setzt voraus, dass ich nicht bereits 9223372036854775807 Zeilen in der Tabelle habe.
Lassen Sie uns Maximus wieder einfügen mit einer niedrigeren ROWID
und versuchen Sie es erneut:
INSERT INTO Dogs VALUES ( 5, 'Maximus' );
SELECT * FROM Dogs;
Ergebnis:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 5 Maximus
Versuchen wir nun, Lickable einzufügen erneut mit AUTOINCREMENT
:
INSERT INTO Dogs VALUES ( NULL, 'Lickable' );
Ergebnis:
Error: database or disk is full
Also, obwohl ich die Zeile gelöscht habe, die die maximale ROWID
enthält Wert von 9223372036854775807, immer noch hindert mich daran, die Spalte automatisch zu inkrementieren.
Genau so wurde es konzipiert. Die maximale ROWID
zuvor in dieser Tabelle gewesen ist und daher AUTOINCREMENT
wird in dieser Tabelle nicht automatisch wieder hochgezählt.
Die einzige Möglichkeit, dieser Tabelle eine neue Zeile hinzuzufügen, besteht darin, die ROWID
manuell einzufügen Wert.
INSERT INTO Dogs VALUES (6, 'Lickable');
SELECT * FROM Dogs;
Ergebnis:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 5 Maximus 6 Lickable