In SQLite, un AUTOINCREMENT
colonna è quella che utilizza un valore incrementato automaticamente per ogni riga inserita nella tabella.
Ci sono un paio di modi per creare un AUTOINCREMENT
colonna:
- Puoi crearlo in modo implicito quando definisci la colonna come
INTEGER PRIMARY KEY
. - Puoi crearlo esplicitamente con
AUTOINCREMENT
parola chiave. Uno svantaggio di questo metodo è che utilizza CPU, memoria, spazio su disco e sovraccarico di I/O su disco aggiuntivi.
Entrambi i metodi fanno sì che la colonna utilizzi un valore incrementale ogni volta che viene inserita una nuova riga con NULL
in quella colonna.
Tuttavia, ci sono alcune sottili differenze nel funzionamento di ciascun metodo.
Senza la parola chiave AUTOINCREMENT
Quando dichiari una colonna come INTEGER PRIMARY KEY
, aumenterà automaticamente. Pertanto, in realtà non è necessario utilizzare AUTOINCREMENT
parola chiave per avere una colonna che utilizza un valore incrementale automaticamente per ogni riga.
Quando lo fai, qualsiasi NULL
i valori vengono convertiti nel ROWID
corrente . In altre parole, se inserisci NULL
in quella colonna, verrà convertito nell'attuale ROWID
.
In realtà, il modo in cui funziona è che la colonna diventa un alias per ROWID
. Puoi accedere al ROWID
valore utilizzando uno qualsiasi dei quattro nomi; il nome della colonna, ROWID
, _ROWID_
o OID
.
Un vantaggio dell'omissione di AUTOINCREMENT
la parola chiave è che riduce il sovraccarico di CPU, memoria, spazio su disco e I/O del disco.
Un aspetto negativo importante, tuttavia, è che non puoi garantire che tutte le righe vengano incrementate in ordine crescente. Ciò è dovuto al modo in cui funziona l'incremento automatico quando si omette AUTOINCREMENT
parola chiave rispetto all'utilizzo di quella parola chiave.
Quando ometti AUTOINCREMENT
parola chiave, una volta ROWID
è uguale al numero intero più grande possibile (9223372036854775807), SQLite proverà a trovare un ROWID
positivo non utilizzato a caso.
Tuttavia, purché non utilizzi mai il massimo ROWID
value e non elimini mai la voce nella tabella con il ROWID
più grande , questo metodo genererà un ROWID
univoco crescente s.
Con la parola chiave AUTOINCREMENT
Puoi anche creare colonne a incremento automatico in modo esplicito. Per fare ciò, usa il AUTOINCREMENT
parola chiave.
Quando si utilizza questo metodo, viene utilizzato un algoritmo leggermente diverso per determinare il valore incrementato automaticamente.
Quando usi AUTOINCREMENT
parola chiave, il ROWID
scelto per la nuova riga è almeno uno più grande del ROWID
più grande che ha mai prima esisteva in quella stessa tabella.
In altre parole, non tornerà indietro e riutilizzerà ROWID
precedentemente cancellato valori. Una volta il più grande ROWID
possibile è stato inserito, non sono consentiti nuovi inserimenti. Qualsiasi tentativo di inserire una nuova riga fallirà con un SQLITE_FULL
errore.
Pertanto l'utilizzo di questo metodo garantisce che il ROWID
s sono monotonicamente crescenti. In altre parole, puoi fare affidamento su questo metodo per avere ROWID
s in ordine crescente.
Ciò non significa che i valori aumenteranno sempre di 1. Significa solo che non diminuiranno mai.
Esempio
Ecco un esempio per dimostrare la differenza tra la definizione implicita ed esplicita di una colonna con incremento automatico.
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;
Risultato iniziale:
CatId CatName ---------- ---------- 1 Brush 2 Scarcat 3 Flutter DogId DogName ---------- ---------- 1 Yelp 2 Woofer 3 Fluff
Ora eliminiamo l'ultima riga di ogni tabella, inseriamo nuovamente le righe, quindi selezioniamo il risultato:
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;
Risultato:
CatId CatName ---------- ---------- 1 Brush 2 Scarcat 3 New Flutter DogId DogName ---------- ---------- 1 Yelp 2 Woofer 4 New Fluff
Per ricapitolare, i Gatti la tabella è stata creata senza il AUTOINCREMENT
parola chiave e Cani la tabella è stata creata con il AUTOINCREMENT
parola chiave.
Dopo aver eliminato l'ultima riga da Cats tabella, il successivo INSERT
l'operazione ha prodotto lo stesso ROWID
riutilizzato per quella riga.
Tuttavia, i Cani il tavolo era diverso. È stato creato con il AUTOINCREMENT
parola chiave e quindi non può riutilizzare il valore precedente. Si incrementa semplicemente al valore successivo, lasciando uno spazio vuoto nella numerazione.
ROWID massimo
Possiamo fare un ulteriore passo avanti nell'esempio precedente e inserire una nuova riga utilizzando esplicitamente il massimo ROWID
possibile.
INSERT INTO Cats VALUES ( 9223372036854775807, 'Magnus' );
INSERT INTO Dogs VALUES ( 9223372036854775807, 'Maximus' );
SELECT * FROM Cats;
SELECT * FROM Dogs;
Risultato:
CatId CatName -------------------- -------------------- 1 Brush 2 Scarcat 3 New Flutter 9223372036854775807 Magnus DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 9223372036854775807 Maximus
OK, quindi entrambe le tabelle usano il numero intero più grande possibile come ROWID
più grande valori.
Vediamo cosa succede quando provo a inserire una nuova riga in ogni tabella (senza specificare esplicitamente un valore per le colonne a incremento automatico).
Inserisci nei Gatti tabella:
INSERT INTO Cats VALUES ( NULL, 'Scratchy' );
SELECT * FROM Cats;
Risultato:
CatId CatName -------------------- -------------------- 1 Brush 2 Scarcat 3 New Flutter 267244677462397326 Scratchy 9223372036854775807 Magnus
Quindi i Gatti il tavolo ha avuto successo. Tuttavia, si noti che il nuovo valore di incremento automatico è inferiore al valore precedente (non ha altre opzioni).
Senza avere un'altra colonna per registrare la data/ora di inserimento/aggiornamento della riga, si potrebbe erroneamente presumere che Magnus è stato inserito dopo Scratchy .
Ora proviamo a inserire una nuova riga nei Cani tabella:
INSERT INTO Dogs VALUES ( NULL, 'Lickable' );
Risultato:
Error: database or disk is full
Quindi otteniamo un risultato diverso rispetto a Cats tabella.
Ho ricevuto questo errore perché il ROWID
più grande possibile è già utilizzato nella tabella e poiché questa tabella è stata creata con AUTOINCREMENT
parola chiave, non tornerà indietro e cercherà un ROWID
inutilizzato valore.
SELECT * FROM Dogs;
Risultato:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 9223372036854775807 Maximus
Inoltre, continuerò a ricevere questo errore, anche se elimino Maximus dalla tabella (ovvero il cane con il massimo ROWID
valore).
Proviamolo:
DELETE FROM Dogs WHERE DogId = 9223372036854775807;
INSERT INTO Dogs VALUES ( NULL, 'Lickable' );
Risultato:
Error: database or disk is full
Quindi non solo riceviamo un errore, ma ho anche eliminato Maximus :
SELECT * FROM Dogs;
Risultato:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff
È importante notare che ciò accadrà anche se cambio il ROWID
valore a un valore inferiore. Il fatto che io abbia già utilizzato un ROWID di 9223372036854775807 significa che AUTOINCREMENT
non aumenterà più automaticamente.
Questo perché AUTOINCREMENT
Utilizza solo valori che sono almeno uno più alti di qualsiasi valore mai esistito in precedenza nella stessa tabella .
D'ora in poi, se volessi continuare a inserire valori in questa colonna, dovrei inserire esplicitamente il valore. Ciò presuppone che io non abbia già 9223372036854775807 righe nella tabella.
Reinseriamo Maximus con un ROWID
inferiore e riprova:
INSERT INTO Dogs VALUES ( 5, 'Maximus' );
SELECT * FROM Dogs;
Risultato:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 5 Maximus
Ora proviamo a inserire Lickable ancora una volta, utilizzando AUTOINCREMENT
:
INSERT INTO Dogs VALUES ( NULL, 'Lickable' );
Risultato:
Error: database or disk is full
Quindi, anche se ho eliminato la riga che contiene il massimo ROWID
valore di 9223372036854775807, ancora mi impedisce di incrementare automaticamente la colonna.
Questo è esattamente come è stato progettato. Il massimo ROWID
è stato precedentemente in questa tabella e quindi AUTOINCREMENT
non aumenterà di nuovo automaticamente in quella tabella.
L'unico modo per aggiungere una nuova riga a quella tabella è inserire manualmente il ROWID
valore.
INSERT INTO Dogs VALUES (6, 'Lickable');
SELECT * FROM Dogs;
Risultato:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 5 Maximus 6 Lickable