I SQLite, en AUTOINCREMENT
kolumn är en som använder ett automatiskt ökat värde för varje rad som infogas i tabellen.
Det finns ett par sätt du kan skapa en AUTOINCREMENT
kolumn:
- Du kan skapa den implicit när du definierar kolumnen som
INTEGER PRIMARY KEY
. - Du kan skapa det uttryckligen med
AUTOINCREMENT
nyckelord. En nackdel med den här metoden är att den använder extra CPU, minne, diskutrymme och disk I/O-overhead.
Båda metoderna gör att kolumnen använder ett ökande värde varje gång en ny rad infogas med NULL
i den kolumnen.
Det finns dock några subtila skillnader mellan hur varje metod fungerar.
Utan AUTOINCREMENT-sökordet
När du deklarerar en kolumn som INTEGER PRIMARY KEY
, kommer den att öka automatiskt. Därför behöver du faktiskt inte använda AUTOINCREMENT
nyckelord för att ha en kolumn som använder ett automatiskt ökande värde för varje rad.
När du gör detta, valfri NULL
värden konverteras till den nuvarande ROWID
. Med andra ord, om du infogar NULL
till den kolumnen kommer den att konverteras till den nuvarande ROWID
.
Egentligen fungerar det så att kolumnen blir ett alias för ROWID
. Du kan komma åt ROWID
värde genom att använda något av fyra namn; kolumnnamnet, ROWID
, _ROWID_
, eller OID
.
En fördel med att utelämna AUTOINCREMENT
nyckelordet är att det minskar CPU, minne, diskutrymme och disk I/O-overhead.
En viktig nackdel är dock att du inte kan garantera att alla rader kommer att ökas i stigande ordning. Detta beror på hur automatisk inkrementering fungerar när AUTOINCREMENT
utelämnas sökord kontra att använda det sökordet.
När du utelämnar AUTOINCREMENT
nyckelord, en gång ROWID
är lika med största möjliga heltal (9223372036854775807), kommer SQLite att försöka hitta en oanvänd positiv ROWID
slumpmässigt.
Men så länge du aldrig använder den maximala ROWID
värde och du tar aldrig bort posten i tabellen med den största ROWID
, kommer denna metod att generera monotont ökande unika ROWID
s.
Med sökordet AUTOINCREMENT
Du kan också skapa automatiskt ökande kolumner explicit. För att göra detta, använd AUTOINCREMENT
nyckelord.
När du använder den här metoden används en något annorlunda algoritm för att bestämma det automatiskt inkrementerade värdet.
När du använder AUTOINCREMENT
sökord, ROWID
vald för den nya raden är minst en större än den största ROWID
som har någonsin tidigare fanns i samma tabell.
Med andra ord, det kommer inte att gå tillbaka och återanvända tidigare raderade ROWID
värden. En gång största möjliga ROWID
har infogats, inga nya inlägg är tillåtna. Alla försök att infoga en ny rad kommer att misslyckas med en SQLITE_FULL
fel.
Användning av denna metod garanterar därför att ROWID
s ökar monotont. Med andra ord kan du lita på den här metoden för att ha ROWID
är i stigande ordning.
Detta betyder dock inte att värdena alltid kommer att öka med 1. Det betyder bara att de aldrig kommer att minska.
Exempel
Här är ett exempel för att visa skillnaden mellan att implicit och explicit definiera en kolumn för automatisk ökning.
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;
Ursprungligt resultat:
CatId CatName ---------- ---------- 1 Brush 2 Scarcat 3 Flutter DogId DogName ---------- ---------- 1 Yelp 2 Woofer 3 Fluff
Låt oss nu ta bort den sista raden i varje tabell, infoga raderna igen och välj sedan resultatet:
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;
Resultat:
CatId CatName ---------- ---------- 1 Brush 2 Scarcat 3 New Flutter DogId DogName ---------- ---------- 1 Yelp 2 Woofer 4 New Fluff
För att sammanfatta, Katter tabellen skapades utan AUTOINCREMENT
sökord och Hundar tabellen skapades med AUTOINCREMENT
nyckelord.
Efter att ha tagit bort den sista raden från Katter tabell, nästa INSERT
operationen resulterade i samma ROWID
återanvänds för den raden.
Men Hundarna bordet var annorlunda. Den skapades med AUTOINCREMENT
sökord och därför kan det inte återanvända det tidigare värdet. Den ökar helt enkelt till nästa värde och lämnar en lucka i numreringen.
Maximal ROWID
Vi kan ta det föregående exemplet ett steg längre och infoga en ny rad genom att uttryckligen använda den maximala ROWID
möjligt.
INSERT INTO Cats VALUES ( 9223372036854775807, 'Magnus' );
INSERT INTO Dogs VALUES ( 9223372036854775807, 'Maximus' );
SELECT * FROM Cats;
SELECT * FROM Dogs;
Resultat:
CatId CatName -------------------- -------------------- 1 Brush 2 Scarcat 3 New Flutter 9223372036854775807 Magnus DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 9223372036854775807 Maximus
OK, så båda tabellerna använder största möjliga heltal som deras största ROWID
värden.
Låt oss se vad som händer när jag försöker infoga en ny rad i varje tabell (utan att uttryckligen ange ett värde för de automatiskt ökande kolumnerna).
Sätt in i Katter tabell:
INSERT INTO Cats VALUES ( NULL, 'Scratchy' );
SELECT * FROM Cats;
Resultat:
CatId CatName -------------------- -------------------- 1 Brush 2 Scarcat 3 New Flutter 267244677462397326 Scratchy 9223372036854775807 Magnus
Alltså Katterna tabellen lyckades. Observera dock att det nya värdet för automatisk ökning är lägre än det tidigare värdet (det har inget annat alternativ).
Utan att ha någon annan kolumn för att registrera datum/tid då raden infogades/uppdaterades, kan man felaktigt anta att Magnus infogades efter Scratchy .
Låt oss nu försöka infoga en ny rad i Hundarna tabell:
INSERT INTO Dogs VALUES ( NULL, 'Lickable' );
Resultat:
Error: database or disk is full
Så vi får ett annat resultat än Katterna bord.
Jag fick det här felet eftersom största möjliga ROWID
används redan i tabellen och eftersom den här tabellen skapades med AUTOINCREMENT
nyckelord, kommer det inte att gå tillbaka och söka efter en oanvänd ROWID
värde.
SELECT * FROM Dogs;
Resultat:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 9223372036854775807 Maximus
Dessutom kommer jag att fortsätta att få detta fel, även om jag tar bort Maximus från tabellen (dvs. hunden med maximal ROWID
värde).
Låt oss prova det:
DELETE FROM Dogs WHERE DogId = 9223372036854775807;
INSERT INTO Dogs VALUES ( NULL, 'Lickable' );
Resultat:
Error: database or disk is full
Så vi får inte bara ett felmeddelande, utan jag har också tagit bort Maximus :
SELECT * FROM Dogs;
Resultat:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff
Det är viktigt att notera att detta kommer att hända även om jag ändrar ROWID
värde till ett lägre värde. Det faktum att jag redan har använt en ROWID på 9223372036854775807 betyder att AUTOINCREMENT
kommer inte längre att öka automatiskt.
Detta beror på att AUTOINCREMENT
använder bara värden som är minst ett högre än något värde som någonsin tidigare har funnits i samma tabell .
Från och med nu, om jag vill fortsätta att infoga värden i den här kolumnen, måste jag uttryckligen infoga värdet. Detta förutsätter att jag inte redan har 9223372036854775807 rader i tabellen.
Låt oss återinföra Maximus med en lägre ROWID
och försök igen:
INSERT INTO Dogs VALUES ( 5, 'Maximus' );
SELECT * FROM Dogs;
Resultat:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 5 Maximus
Låt oss nu försöka infoga Slickbar återigen med AUTOINCREMENT
:
INSERT INTO Dogs VALUES ( NULL, 'Lickable' );
Resultat:
Error: database or disk is full
Så även om jag har tagit bort raden som innehåller den maximala ROWID
värdet på 9223372036854775807, det fortfarande hindrar mig från att automatiskt öka kolumnen.
Det är precis så det är designat. Det maximala ROWID
har tidigare funnits i den här tabellen och så AUTOINCREMENT
kommer inte automatiskt att öka igen i den tabellen.
Det enda sättet att lägga till en ny rad i den tabellen är att manuellt infoga ROWID
värde.
INSERT INTO Dogs VALUES (6, 'Lickable');
SELECT * FROM Dogs;
Resultat:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 5 Maximus 6 Lickable