No SQLite, um
AUTOINCREMENT
coluna é aquela que usa um valor incrementado automaticamente para cada linha inserida na tabela. Existem algumas maneiras de criar um
AUTOINCREMENT
coluna:- Você pode criá-lo implicitamente ao definir a coluna como
INTEGER PRIMARY KEY
. - Você pode criá-lo explicitamente com o
AUTOINCREMENT
palavra-chave. Uma desvantagem desse método é que ele usa CPU extra, memória, espaço em disco e sobrecarga de E/S de disco.
Ambos os métodos fazem com que a coluna use um valor de incremento cada vez que uma nova linha é inserida com
NULL
nessa coluna. No entanto, existem algumas diferenças sutis entre como cada método funciona.
Sem a palavra-chave AUTOINCREMENT
Quando você declara uma coluna como
INTEGER PRIMARY KEY
, ele será incrementado automaticamente. Portanto, você não precisa usar o AUTOINCREMENT
palavra-chave para ter uma coluna que usa um valor de incremento automático para cada linha. Ao fazer isso, qualquer
NULL
os valores são convertidos no ROWID
atual . Em outras palavras, se você inserir NULL
nessa coluna, ela será convertida para o ROWID
atual . Na verdade, a forma como funciona é que a coluna se torna um alias para o
ROWID
. Você pode acessar o ROWID
valor usando qualquer um dos quatro nomes; o nome da coluna, ROWID
, _ROWID_
, ou OID
. Uma vantagem de omitir o
AUTOINCREMENT
palavra-chave é que ela reduz CPU, memória, espaço em disco e sobrecarga de E/S de disco. Uma desvantagem importante, no entanto, é que você não pode garantir que todas as linhas serão incrementadas em ordem crescente. Isso se deve ao modo como o incremento automático funciona ao omitir o
AUTOINCREMENT
palavra-chave vs usando essa palavra-chave. Quando você omite o
AUTOINCREMENT
palavra-chave, uma vez ROWID
for igual ao maior inteiro possível (9223372036854775807), o SQLite tentará encontrar um ROWID
positivo não utilizado aleatoriamente. No entanto, contanto que você nunca use o máximo de
ROWID
valor e você nunca exclui a entrada na tabela com o maior ROWID
, este método irá gerar um ROWID
único monotonicamente crescente s. Com a palavra-chave AUTOINCREMENT
Você também pode criar colunas de incremento automático explicitamente. Para fazer isso, use o
AUTOINCREMENT
palavra-chave. Quando você usa esse método, um algoritmo ligeiramente diferente é usado para determinar o valor incrementado automaticamente.
Quando você usa o
AUTOINCREMENT
palavra-chave, o ROWID
escolhido para a nova linha é pelo menos um maior que o maior ROWID
que nunca antes existia nessa mesma tabela. Em outras palavras, ele não voltará e reutilizará
ROWID
excluído anteriormente valores. Uma vez que o maior possível ROWID
foi inserido, não são permitidas novas inserções. Qualquer tentativa de inserir uma nova linha falhará com um SQLITE_FULL
erro. Portanto, usar este método garante que o
ROWID
s são crescentes monotonicamente. Em outras palavras, você pode confiar neste método para ter ROWID
s em ordem crescente. Isso não significa que os valores sempre serão incrementados em 1. Significa apenas que eles nunca diminuirão.
Exemplo
Aqui está um exemplo para demonstrar a diferença entre definir implicitamente e explicitamente uma coluna de incremento automático.
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;
Resultado inicial:
CatId CatName ---------- ---------- 1 Brush 2 Scarcat 3 Flutter DogId DogName ---------- ---------- 1 Yelp 2 Woofer 3 Fluff
Agora vamos excluir a última linha de cada tabela, inserir as linhas novamente e selecionar o resultado:
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;
Resultado:
CatId CatName ---------- ---------- 1 Brush 2 Scarcat 3 New Flutter DogId DogName ---------- ---------- 1 Yelp 2 Woofer 4 New Fluff
Para recapitular, os Gatos a tabela foi criada sem o
AUTOINCREMENT
palavra-chave e Cães a tabela foi criada com o AUTOINCREMENT
palavra-chave. Depois de excluir a última linha de Gatos tabela, o próximo
INSERT
operação resultou no mesmo ROWID
sendo reutilizado para essa linha. No entanto, os Cães mesa era diferente. Ele foi criado com o
AUTOINCREMENT
palavra-chave e, portanto, não pode reutilizar o valor anterior. Ele simplesmente incrementa para o próximo valor, deixando uma lacuna na numeração. ROWID máximo
Podemos levar o exemplo anterior um passo adiante e inserir uma nova linha usando explicitamente o máximo
ROWID
possível. INSERT INTO Cats VALUES ( 9223372036854775807, 'Magnus' );
INSERT INTO Dogs VALUES ( 9223372036854775807, 'Maximus' );
SELECT * FROM Cats;
SELECT * FROM Dogs;
Resultado:
CatId CatName -------------------- -------------------- 1 Brush 2 Scarcat 3 New Flutter 9223372036854775807 Magnus DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 9223372036854775807 Maximus
OK, então ambas as tabelas usam o maior inteiro possível como seu maior
ROWID
valores. Vamos ver o que acontece quando tento inserir uma nova linha em cada tabela (sem especificar explicitamente um valor para as colunas de incremento automático).
Insira nos Gatos tabela:
INSERT INTO Cats VALUES ( NULL, 'Scratchy' );
SELECT * FROM Cats;
Resultado:
CatId CatName -------------------- -------------------- 1 Brush 2 Scarcat 3 New Flutter 267244677462397326 Scratchy 9223372036854775807 Magnus
Então os Gatos mesa foi bem sucedida. No entanto, observe que o novo valor de incremento automático é menor que o valor anterior (não há outra opção).
Sem ter nenhuma outra coluna para registrar a data/hora em que a linha foi inserida/atualizada, pode-se supor incorretamente que Magnus foi inserido após Scratchy .
Agora vamos tentar inserir uma nova linha no Cães tabela:
INSERT INTO Dogs VALUES ( NULL, 'Lickable' );
Resultado:
Error: database or disk is full
Assim, obtemos um resultado diferente dos Gatos tabela.
Recebi este erro porque o maior
ROWID
possível já está sendo usado na tabela, e porque esta tabela foi criada com o AUTOINCREMENT
palavra-chave, ele não voltará e procurará um ROWID
não utilizado valor. SELECT * FROM Dogs;
Resultado:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 9223372036854775807 Maximus
Além disso, continuarei recebendo esse erro, mesmo se excluir Maximus da tabela (ou seja, o cão com o máximo de
ROWID
valor). Vamos tentar:
DELETE FROM Dogs WHERE DogId = 9223372036854775807;
INSERT INTO Dogs VALUES ( NULL, 'Lickable' );
Resultado:
Error: database or disk is full
Portanto, não apenas recebemos um erro, mas também excluí Maximus :
SELECT * FROM Dogs;
Resultado:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff
É importante observar que isso acontecerá mesmo se eu alterar o
ROWID
valor para um valor inferior. O fato de eu já ter usado um ROWID de 9223372036854775807 significa que AUTOINCREMENT
não será mais incrementado automaticamente. Isso ocorre porque
AUTOINCREMENT
usa apenas valores que são pelo menos um valor mais alto do que qualquer valor que já existiu na mesma tabela . A partir de agora, se eu quisesse continuar inserindo valores nessa coluna, precisaria inserir explicitamente o valor. Isso pressupõe que eu ainda não tenha 9223372036854775807 linhas na tabela.
Vamos reinserir o Maximus com um
ROWID
menor e tente novamente:INSERT INTO Dogs VALUES ( 5, 'Maximus' );
SELECT * FROM Dogs;
Resultado:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 5 Maximus
Agora vamos tentar inserir Lickable mais uma vez, usando
AUTOINCREMENT
:INSERT INTO Dogs VALUES ( NULL, 'Lickable' );
Resultado:
Error: database or disk is full
Portanto, embora eu tenha excluído a linha que contém o máximo de
ROWID
valor de 9223372036854775807, ainda me impede de incrementar automaticamente a coluna. É exatamente assim que foi projetado. O máximo de
ROWID
esteve anteriormente nesta tabela e, portanto, AUTOINCREMENT
não será incrementado automaticamente novamente nessa tabela. A única maneira de adicionar uma nova linha a essa tabela é inserir manualmente o
ROWID
valor. INSERT INTO Dogs VALUES (6, 'Lickable');
SELECT * FROM Dogs;
Resultado:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 5 Maximus 6 Lickable