sql >> Database >  >> RDS >> SQLite

Hoe AUTOINCREMENT werkt in SQLite

In SQLite, een AUTOINCREMENT kolom is er een die een automatisch verhoogde waarde gebruikt voor elke rij die in de tabel wordt ingevoegd.

Er zijn een aantal manieren waarop u een AUTOINCREMENT . kunt maken kolom:

  • U kunt het impliciet maken als u de kolom definieert als INTEGER PRIMARY KEY .
  • Je kunt het expliciet maken met de AUTOINCREMENT trefwoord. Een nadeel van deze methode is dat het extra CPU, geheugen, schijfruimte en schijf-I/O-overhead gebruikt.

Beide methoden zorgen ervoor dat de kolom een ​​oplopende waarde gebruikt telkens wanneer een nieuwe rij wordt ingevoegd met NULL in die kolom.

Er zijn echter enkele subtiele verschillen tussen hoe elke methode werkt.

Zonder het AUTOINCREMENT-zoekwoord

Wanneer u een kolom declareert als INTEGER PRIMARY KEY , wordt deze automatisch verhoogd. Daarom hoeft u de AUTOINCREMENT . niet te gebruiken zoekwoord om een ​​kolom te hebben die een automatisch oplopende waarde gebruikt voor elke rij.

Wanneer u dit doet, wordt elke NULL waarden worden geconverteerd naar de huidige ROWID . Met andere woorden, als u NULL . invoegt in die kolom, wordt het geconverteerd naar de huidige ROWID .

De manier waarop het werkt, is dat de kolom een ​​alias wordt voor de ROWID . U heeft toegang tot de ROWID waarde door een van de vier namen te gebruiken; de kolomnaam, ROWID , _ROWID_ , of OID .

Een voordeel van het weglaten van de AUTOINCREMENT sleutelwoord is dat het CPU, geheugen, schijfruimte en schijf-I/O-overhead vermindert.

Een belangrijk nadeel is echter dat u niet kunt garanderen dat alle rijen in oplopende volgorde worden verhoogd. Dit komt door de manier waarop automatisch verhogen werkt bij het weglaten van de AUTOINCREMENT zoekwoord versus het gebruik van dat zoekwoord.

Wanneer u de AUTOINCREMENT . weglaat zoekwoord, eenmaal ROWID gelijk is aan het grootst mogelijke gehele getal (9223372036854775807), zal SQLite proberen een ongebruikte positieve ROWID te vinden willekeurig.

Zolang u echter nooit de maximale ROWID . gebruikt waarde en u verwijdert nooit het item in de tabel met de grootste ROWID , genereert deze methode monotoon toenemende unieke ROWID v.

Met het AUTOINCREMENT-zoekwoord

U kunt ook expliciet automatisch oplopende kolommen maken. Gebruik hiervoor de AUTOINCREMENT trefwoord.

Wanneer u deze methode gebruikt, wordt een iets ander algoritme gebruikt om de automatisch verhoogde waarde te bepalen.

Wanneer u de AUTOINCREMENT . gebruikt zoekwoord, de ROWID gekozen voor de nieuwe rij is minstens één groter dan de grootste ROWID dat heeft ooit bestond eerder in diezelfde tabel.

Met andere woorden, het gaat niet terug en hergebruikt eerder verwijderde ROWID waarden. Eens de grootst mogelijke ROWID is ingevoegd, zijn geen nieuwe invoegingen toegestaan. Elke poging om een ​​nieuwe rij in te voegen mislukt met een SQLITE_FULL fout.

Daarom garandeert het gebruik van deze methode dat de ROWID s nemen monotoon toe. Met andere woorden, u kunt op deze methode vertrouwen om ROWID . te hebben s in oplopende volgorde.

Dit betekent echter niet dat de waarden altijd met 1 zullen toenemen. Het betekent alleen dat ze nooit zullen afnemen.

Voorbeeld

Hier is een voorbeeld om het verschil aan te tonen tussen het impliciet en expliciet definiëren van een kolom voor automatisch ophogen.

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;

Eerste resultaat:

CatId       CatName   
----------  ----------
1           Brush     
2           Scarcat   
3           Flutter  

DogId       DogName   
----------  ----------
1           Yelp      
2           Woofer    
3           Fluff      

Laten we nu de laatste rij in elke tabel verwijderen, de rijen opnieuw invoegen en het resultaat selecteren:

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;

Resultaat:

CatId       CatName   
----------  ----------
1           Brush     
2           Scarcat   
3           New Flutter

DogId       DogName   
----------  ----------
1           Yelp      
2           Woofer    
4           New Fluff 

Om samen te vatten, de Katten tabel is gemaakt zonder de AUTOINCREMENT zoekwoord, en de Honden tabel is gemaakt met de AUTOINCREMENT zoekwoord.

Na het verwijderen van de laatste rij uit de Cats tabel, de volgende INSERT operatie resulteerde in dezelfde ROWID wordt hergebruikt voor die rij.

Echter, de Honden tafel was anders. Het is gemaakt met de AUTOINCREMENT zoekwoord en daarom kan het de vorige waarde niet opnieuw gebruiken. Het wordt gewoon verhoogd naar de volgende waarde, waardoor er een gat in de nummering blijft.

Maximale ROWID

We kunnen het vorige voorbeeld een stap verder nemen en een nieuwe rij invoegen door expliciet de maximale ROWID te gebruiken mogelijk.

INSERT INTO Cats VALUES ( 9223372036854775807, 'Magnus' );
INSERT INTO Dogs VALUES ( 9223372036854775807, 'Maximus' );

SELECT * FROM Cats;
SELECT * FROM Dogs;

Resultaat:

CatId                 CatName             
--------------------  --------------------
1                     Brush               
2                     Scarcat             
3                     New Flutter         
9223372036854775807   Magnus              

DogId                 DogName             
--------------------  --------------------
1                     Yelp                
2                     Woofer              
4                     New Fluff           
9223372036854775807   Maximus             

OK, dus beide tabellen gebruiken het grootst mogelijke gehele getal als hun grootste ROWID waarden.

Laten we eens kijken wat er gebeurt als ik een nieuwe rij in elke tabel probeer in te voegen (zonder expliciet een waarde op te geven voor de automatisch oplopende kolommen).

Invoegen in de Katten tafel:

INSERT INTO Cats VALUES ( NULL, 'Scratchy' );
SELECT * FROM Cats;

Resultaat:

CatId                 CatName             
--------------------  --------------------
1                     Brush               
2                     Scarcat             
3                     New Flutter         
267244677462397326    Scratchy            
9223372036854775807   Magnus              

Dus de Katten tafel is gelukt. Merk echter op dat de nieuwe waarde voor automatisch ophogen lager is dan de vorige waarde (het heeft geen andere optie).

Zonder een andere kolom om de datum/tijd vast te leggen waarop de rij is ingevoegd/bijgewerkt, zou men ten onrechte kunnen aannemen dat Magnus werd ingevoegd na Scratchy .

Laten we nu proberen een nieuwe rij in te voegen in de Honden tafel:

INSERT INTO Dogs VALUES ( NULL, 'Lickable' );

Resultaat:

Error: database or disk is full

We krijgen dus een ander resultaat dan de Katten tafel.

Ik kreeg deze fout omdat de grootst mogelijke ROWID al in de tabel wordt gebruikt, en omdat deze tabel is gemaakt met de AUTOINCREMENT zoekwoord, zal het niet teruggaan en zoeken naar een ongebruikte ROWID waarde.

SELECT * FROM Dogs;

Resultaat:

DogId                 DogName             
--------------------  --------------------
1                     Yelp                
2                     Woofer              
4                     New Fluff           
9223372036854775807   Maximus             

Bovendien blijf ik deze fout krijgen, zelfs als ik Maximus . verwijder uit de tabel (d.w.z. de hond met de maximale ROWID waarde).

Laten we het proberen:

DELETE FROM Dogs WHERE DogId = 9223372036854775807;
INSERT INTO Dogs VALUES ( NULL, 'Lickable' );

Resultaat:

Error: database or disk is full

We krijgen dus niet alleen een foutmelding, maar ik heb ook Maximus . verwijderd :

SELECT * FROM Dogs;

Resultaat:

DogId                 DogName             
--------------------  --------------------
1                     Yelp                
2                     Woofer              
4                     New Fluff           

Het is belangrijk op te merken dat dit ook gebeurt als ik de ROWID . wijzig waarde naar een lagere waarde. Het feit dat ik al een ROWID van 9223372036854775807 heb gebruikt, betekent dat AUTOINCREMENT wordt niet meer automatisch verhoogd.

Dit komt omdat AUTOINCREMENT gebruikt alleen waarden die ten minste één hoger zijn dan enige waarde die ooit eerder in diezelfde tabel heeft bestaan .

Als ik voortaan waarden in deze kolom wilde blijven invoegen, zou ik de waarde expliciet moeten invoegen. Dit veronderstelt dat ik nog geen 9223372036854775807 rijen in de tabel heb.

Laten we Maximus opnieuw invoegen met een lagere ROWID en probeer het opnieuw:

INSERT INTO Dogs VALUES ( 5, 'Maximus' );
SELECT * FROM Dogs;

Resultaat:

DogId                 DogName             
--------------------  --------------------
1                     Yelp                
2                     Woofer              
4                     New Fluff           
5                     Maximus            

Laten we nu proberen Lickable . in te voegen nogmaals, met behulp van AUTOINCREMENT :

INSERT INTO Dogs VALUES ( NULL, 'Lickable' );

Resultaat:

Error: database or disk is full

Dus ook al heb ik de rij verwijderd die de maximale ROWID bevat waarde van 9223372036854775807, het nog voorkomt dat ik de kolom automatisch kan verhogen.

Dit is precies hoe het is ontworpen. De maximale ROWID heeft eerder in deze tabel gestaan ​​en dus AUTOINCREMENT wordt niet automatisch opnieuw verhoogd in die tabel.

De enige manier om een ​​nieuwe rij aan die tabel toe te voegen, is door handmatig de ROWID . in te voegen waarde.

INSERT INTO Dogs VALUES (6, 'Lickable');
SELECT * FROM Dogs;

Resultaat:

DogId                 DogName             
--------------------  --------------------
1                     Yelp                
2                     Woofer              
4                     New Fluff           
5                     Maximus             
6                     Lickable            


  1. Mysql-dumps en -importen versnellen

  2. Hoe kan ik een rij in een tabel BIJWERKEN of INVOEREN als deze niet bestaat?

  3. Gegevens voor elk uur ophalen in MySQL

  4. Big data sneller laden