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
AUTOINCREMENTpalavra-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