sql >> Databáze >  >> RDS >> SQLite

Jak funguje AUTOINCREMENT v SQLite

V SQLite, AUTOINCREMENT sloupec je ten, který používá automaticky zvýšenou hodnotu pro každý řádek, který je vložen do tabulky.

Existuje několik způsobů, jak vytvořit AUTOINCREMENT sloupec:

  • Můžete jej vytvořit implicitně, když sloupec definujete jako INTEGER PRIMARY KEY .
  • Můžete jej vytvořit explicitně pomocí AUTOINCREMENT klíčové slovo. Jednou nevýhodou této metody je, že využívá extra CPU, paměť, místo na disku a režii diskových I/O.

Obě metody způsobí, že sloupec použije zvyšující se hodnotu pokaždé, když je vložen nový řádek s NULL v tom sloupci.

Mezi tím, jak jednotlivé metody fungují, však existují jemné rozdíly.

Bez klíčového slova AUTOINCREMENT

Když deklarujete sloupec jako INTEGER PRIMARY KEY , automaticky se zvýší. Proto ve skutečnosti nemusíte používat AUTOINCREMENT klíčové slovo, aby měl sloupec, který používá automaticky se zvyšující hodnotu pro každý řádek.

Když to uděláte, všechny NULL hodnoty jsou převedeny na aktuální ROWID . Jinými slovy, pokud vložíte NULL do tohoto sloupce, bude převeden na aktuální ROWID .

Ve skutečnosti to funguje tak, že sloupec se stane aliasem pro ROWID . Máte přístup k ROWID hodnotu pomocí kteréhokoli ze čtyř jmen; název sloupce ROWID , _ROWID_ nebo OID .

Jednou z výhod vynechání AUTOINCREMENT klíčové slovo je, že snižuje CPU, paměť, místo na disku a režii I/O disku.

Důležitou nevýhodou však je, že nemůžete zaručit, že se všechny řádky budou zvyšovat ve vzestupném pořadí. Je to způsobeno tím, jak funguje automatické zvyšování při vynechání AUTOINCREMENT klíčové slovo vs používání tohoto klíčového slova.

Když vynecháte AUTOINCREMENT klíčové slovo, jednou ROWID se rovná největšímu možnému celému číslu (9223372036854775807), SQLite se pokusí najít nepoužitý kladný ROWID náhodně.

Pokud však nikdy nepoužijete maximální ROWID hodnotu a nikdy neodstraníte záznam v tabulce s největším ROWID , bude tato metoda generovat monotónně rostoucí unikátní ROWID s.

S klíčovým slovem AUTOINCREMENT

Můžete také explicitně vytvořit automaticky se zvyšující sloupce. K tomu použijte AUTOINCREMENT klíčové slovo.

Když použijete tuto metodu, použije se k určení automaticky zvýšené hodnoty mírně odlišný algoritmus.

Když použijete AUTOINCREMENT klíčové slovo ROWID vybraný pro nový řádek je alespoň o jeden větší než největší ROWID který má kdy dříve existoval ve stejné tabulce.

Jinými slovy, nevrátí se a znovu nepoužije dříve smazaný ROWID hodnoty. Jednou největší možný ROWID byl vložen, nejsou povoleny žádné nové vložky. Jakýkoli pokus o vložení nového řádku selže s SQLITE_FULL chyba.

Proto použití této metody zaručuje, že ROWID s monotónně přibývají. Jinými slovy, na tuto metodu se můžete spolehnout, že budete mít ROWID s ve vzestupném pořadí.

To však neznamená, že se hodnoty vždy zvýší o 1. Znamená to pouze, že se nikdy nesníží.

Příklad

Zde je příklad, který demonstruje rozdíl mezi implicitním a explicitním definováním sloupce automatického zvýšení.

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;

Počáteční výsledek:

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

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

Nyní smažeme poslední řádek v každé tabulce, vložíme řádky znovu a vybereme výsledek:

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;

Výsledek:

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

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

Pro rekapitulaci, Kočky tabulka byla vytvořena bez AUTOINCREMENT klíčové slovo a Psi tabulka byla vytvořena pomocí AUTOINCREMENT klíčové slovo.

Po smazání posledního řádku z Kočky tabulka, další INSERT operace vedla ke stejnému ROWID znovu použit pro daný řádek.

Nicméně Psi stůl byl jiný. Byl vytvořen pomocí AUTOINCREMENT klíčové slovo, a proto nemůže znovu použít předchozí hodnotu. Jednoduše se zvýší na další hodnotu, přičemž v číslování zůstane mezera.

Maximální ROWID

Předchozí příklad můžeme udělat o krok dále a vložit nový řádek explicitním použitím maximálního ROWID možné.

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

SELECT * FROM Cats;
SELECT * FROM Dogs;

Výsledek:

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

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

Dobře, takže obě tabulky používají největší možné celé číslo jako největší ROWID hodnoty.

Podívejme se, co se stane, když se pokusím vložit nový řádek do každé tabulky (bez explicitního zadání hodnoty pro automaticky se zvyšující sloupce).

Vložte do Kočky tabulka:

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

Výsledek:

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

Takže Kočky tabulka byla úspěšná. Všimněte si však, že nová hodnota automatického zvýšení je nižší než předchozí hodnota (nemá jinou možnost).

Bez dalšího sloupce pro záznam data/času, kdy byl řádek vložen/aktualizován, by se dalo nesprávně předpokládat, že Magnus byl vložen za Scratchy .

Nyní se pokusíme vložit nový řádek do Psi tabulka:

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

Výsledek:

Error: database or disk is full

Dostaneme tedy jiný výsledek než Kočky tabulka.

Dostal jsem tuto chybu, protože největší možný ROWID se již v tabulce používá, a protože tato tabulka byla vytvořena pomocí AUTOINCREMENT klíčové slovo, nevrátí se a nebude hledat nepoužitý ROWID hodnotu.

SELECT * FROM Dogs;

Výsledek:

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

Navíc se mi tato chyba bude zobrazovat i nadále, i když smažu Maximus ze stolu (tj. pes s maximálním ROWID hodnota).

Zkusme to:

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

Výsledek:

Error: database or disk is full

Nejenže se nám zobrazí chyba, ale také jsem smazal Maximus :

SELECT * FROM Dogs;

Výsledek:

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

Je důležité si uvědomit, že k tomu dojde, i když změním ROWID hodnotu na nižší hodnotu. Skutečnost, že jsem již použil ROWID 9223372036854775807, znamená, že AUTOINCREMENT se již nebude automaticky zvyšovat.

Důvodem je AUTOINCREMENT používá pouze hodnoty, které jsou alespoň o jednu vyšší než jakákoliv hodnota, která kdy v téže tabulce existovala .

Od této chvíle, pokud bych chtěl i nadále vkládat hodnoty do tohoto sloupce, musel bych hodnotu vkládat explicitně. To předpokládá, že v tabulce již nemám 9223372036854775807 řádků.

Znovu vložíme Maximus s nižším ROWID a zkuste to znovu:

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

Výsledek:

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

Nyní zkusme vložit Lickable ještě jednou pomocí AUTOINCREMENT :

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

Výsledek:

Error: database or disk is full

Takže i když jsem smazal řádek, který obsahuje maximální ROWID hodnota 9223372036854775807, stále mi brání v automatickém zvyšování sloupce.

Přesně tak to bylo navrženo. Maximální ROWID byl dříve v této tabulce, a tak AUTOINCREMENT se v této tabulce automaticky znovu nezvýší.

Jediným způsobem, jak do tabulky přidat nový řádek, je ručně vložit ROWID hodnotu.

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

Výsledek:

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


  1. Jak používat SqlTransaction v C#

  2. Jak by DevOps měli používat DBaaS (databáze jako služba) k optimalizaci vývoje svých aplikací​

  3. Zaregistrujte se a spusťte PostgreSQL 9.0 jako službu Windows

  4. Jak propojit tabulku s backendovou databází v Accessu 2016