sql >> Databasteknik >  >> RDS >> SQLite

Hur AUTOINCREMENT fungerar i SQLite

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            


  1. TNS-12519 utan maximala processer uppnådda

  2. olöst referens till objektet [INFORMATION_SCHEMA].[TABLER]

  3. Hur man hittar minimivärden i kolumner

  4. postgresql trådsäkerhet för tillfälliga tabeller