SQL AUTOINCREMENT
Toda vez que a Loja Aurora ganha um cliente novo, ele precisa de um número: o id. Quem escolhe esse número? Se fosse a Ana, ela teria de olhar qual foi o último, somar 1 e torcer para ninguém cadastrar outro cliente ao mesmo tempo. Ainda bem que o banco faz isso sozinho. Nesta aula você vai ver que, no SQLite, a coluna INTEGER PRIMARY KEY já se numera sozinha, e o que a palavra AUTOINCREMENT ("incremento automático") acrescenta: a garantia de que um número usado nunca volta.
- Como o
INTEGER PRIMARY KEYescolhe o id de cada linha nova, sem você digitar nada. - O que é o
rowid, o número escondido de toda tabela do SQLite. - Por que, sem
AUTOINCREMENT, um número apagado pode ser reaproveitado. - O que o
AUTOINCREMENTmuda, e a tabelasqlite_sequence, onde ele guarda a conta. - Quando vale a pena usar
AUTOINCREMENT(quase nunca) e quando não. - Os erros reais:
AUTOINCREMENT is only allowed on an INTEGER PRIMARY KEY, oAUTO_INCREMENTdo MySQL e oINT PRIMARY KEYque deixa o id vazio. - Como o MySQL, o PostgreSQL e o SQL Server fazem a mesma coisa.
Esta aula continua a de PRIMARY KEY. Todos os exemplos rodam de verdade no seu navegador, contra o banco da Loja Aurora, e cada um começa do banco limpo.
A ideia: duas maneiras de numerar fichas
Imagine dois jeitos de numerar as fichas dos clientes num fichário:
| Jeito | Como funciona | O que acontece se você jogar fora a última ficha |
|---|---|---|
| "O maior + 1" | Para a ficha nova, você olha o maior número que está no fichário e soma 1. | O número dela fica livre de novo: a próxima ficha ganha o mesmo número. |
| Talão numerado | Você usa um talão com as folhas já numeradas. Cada ficha nova é a próxima folha do talão. | A folha arrancada não volta. A próxima ficha ganha o número seguinte, e fica um "buraco". |
No SQLite, o INTEGER PRIMARY KEY sozinho é o primeiro jeito. Com AUTOINCREMENT, vira o segundo. Os dois numeram sozinhos; a diferença só aparece quando você apaga linhas.
1. O INTEGER PRIMARY KEY já numera sozinho
A tabela clientes da Loja Aurora foi criada assim (só as primeiras colunas):
CREATE TABLE clientes (
id INTEGER PRIMARY KEY,
nome TEXT NOT NULL,
...
);
Não tem AUTOINCREMENT nenhum. Mesmo assim, veja o que acontece quando a Ana cadastra a cliente Rita Moura sem dizer o id:
INSERT INTO clientes (nome, cidade, estado)
VALUES ('Rita Moura', 'Teresina', 'PI');
SELECT id, nome, cidade
FROM clientes
WHERE id > 28;
- INSERT INTO clientes (nome, cidade, estado)
- A lista de colunas não tem o
id. As colunas que ficaram de fora recebem o valor padrão (veja DEFAULT); para oid, o "padrão" é um número novo. - VALUES ('Rita Moura', 'Teresina', 'PI')
- Os valores, na mesma ordem da lista.
- WHERE id > 28
- Só para mostrar o fim da tabela: os clientes 29 e 30, que já existiam, e a Rita.
A Rita ganhou o 31. A Loja Aurora tinha os clientes de 1 a 30, e o SQLite fez a conta "o maior + 1". Dá o mesmo resultado se você escrever o id como NULL: INSERT INTO clientes (id, nome) VALUES (NULL, 'Rita Moura');. Para o INTEGER PRIMARY KEY, NULL quer dizer "escolha você".
Qual número a linha ganhou?
Num programa de verdade, logo depois de cadastrar o cliente você quer saber o número dele (para gravar o pedido, por exemplo). A função last_insert_rowid() ("o último rowid inserido") devolve exatamente isso:
INSERT INTO clientes (nome, cidade, estado)
VALUES ('Rita Moura', 'Teresina', 'PI');
SELECT last_insert_rowid();
Toda tabela comum do SQLite tem um número escondido em cada linha, o rowid ("id da linha"). Ele existe mesmo que você não crie coluna nenhuma para isso. Quando você declara uma coluna INTEGER PRIMARY KEY, ela vira um outro nome para o rowid: são a mesma coisa. Por isso ela se numera sozinha. Repare no nome da primeira coluna do resultado abaixo: o SQLite chamou o rowid de id, porque, nesta tabela, é a mesma coluna.
SELECT rowid, id, nome FROM clientes LIMIT 3;
Experimente: o código mostra os três últimos clientes. Antes do SELECT, cadastre a cliente Rita Moura, de Teresina (PI), sem informar o id, e veja qual número ela ganha.
SELECT id, nome FROM clientes ORDER BY id DESC LIMIT 3;
INSERT INTO clientes (nome, cidade, estado)
VALUES ('Rita Moura', 'Teresina', 'PI');
SELECT id, nome
FROM clientes
ORDER BY id DESC
LIMIT 3;
2. O problema: o número apagado volta
A regra "o maior + 1" tem uma consequência. O cliente 30, Rosângela Dias, nunca fez pedido. Suponha que a Ana apague o cadastro dela e, depois, cadastre a Rita:
DELETE FROM clientes WHERE id = 30;
INSERT INTO clientes (nome, cidade, estado)
VALUES ('Rita Moura', 'Teresina', 'PI');
SELECT id, nome
FROM clientes
WHERE id >= 28;
A Rita ganhou o 30, o número que era da Rosângela. Depois do DELETE, o maior id da tabela passou a ser 29, e 29 + 1 = 30. O número foi reaproveitado.
Isso só acontece com o último número. Se a Ana apagar um cliente do meio, o buraco fica, porque o maior continua lá em cima:
DELETE FROM clientes WHERE id = 28;
INSERT INTO clientes (nome, cidade, estado)
VALUES ('Rita Moura', 'Teresina', 'PI');
SELECT id, nome
FROM clientes
WHERE id >= 27;
O 28 sumiu e a Rita ganhou o 31. Na maioria dos sistemas, reaproveitar o último número não faz mal nenhum. Mas pense numa situação em que faz: a Rosângela tinha recebido um email "seu cadastro é o número 30", ou um sistema de fora guardou "cliente 30 = Rosângela". Agora o 30 é outra pessoa. É para esses casos que existe o AUTOINCREMENT.
3. AUTOINCREMENT: o número nunca volta
A Ana vai criar uma tabela de cupons de desconto. Cupom é coisa que vai para a rua: está impresso em folheto, foi mandado por mensagem. Um número de cupom apagado não pode voltar como outro cupom. Ela escreve:
CREATE TABLE cupons (
id INTEGER PRIMARY KEY AUTOINCREMENT,
codigo TEXT NOT NULL,
desconto REAL NOT NULL
);
INSERT INTO cupons (codigo, desconto)
VALUES ('BEMVINDO', 10), ('NATAL', 15), ('PIAUI', 5);
SELECT * FROM cupons;
- id
- O nome da coluna.
- INTEGER
- O tipo, escrito exatamente assim:
INTEGER. ComINT,BIGINTou outro nome, não funciona (veja Quando dá errado). - PRIMARY KEY
- A chave primária: o número que identifica cada cupom.
- AUTOINCREMENT
- "Incremento automático": o número escolhido para uma linha nova é sempre maior que todos os que já existiram nesta tabela, inclusive os que foram apagados. Só pode vir logo depois de
INTEGER PRIMARY KEY.
Até aqui, nenhuma diferença: 1, 2, 3. Agora o teste que importa. O cupom 3, PIAUI, foi cancelado, e a Ana cria o cupom VERAO:
CREATE TABLE cupons (
id INTEGER PRIMARY KEY AUTOINCREMENT,
codigo TEXT NOT NULL,
desconto REAL NOT NULL
);
INSERT INTO cupons (codigo, desconto)
VALUES ('BEMVINDO', 10), ('NATAL', 15), ('PIAUI', 5);
DELETE FROM cupons WHERE id = 3;
INSERT INTO cupons (codigo, desconto) VALUES ('VERAO', 20);
SELECT * FROM cupons;
O VERAO ganhou o 4, e não o 3. Mesmo que alguém ainda tenha o folheto do cupom 3 na mão, esse número nunca vai apontar para outro cupom. Compare com o que aconteceu com a Rita na seção 2.
Onde o SQLite guarda a conta: sqlite_sequence
Para lembrar do maior número que já existiu (mesmo depois de apagado), o SQLite precisa anotá-lo em algum lugar. Quando você cria a primeira tabela com AUTOINCREMENT, ele cria sozinho uma tabela interna chamada sqlite_sequence ("sequência do SQLite"), com uma linha por tabela:
CREATE TABLE cupons (
id INTEGER PRIMARY KEY AUTOINCREMENT,
codigo TEXT NOT NULL,
desconto REAL NOT NULL
);
INSERT INTO cupons (codigo, desconto)
VALUES ('BEMVINDO', 10), ('NATAL', 15), ('PIAUI', 5);
DELETE FROM cupons WHERE id = 3;
SELECT name, seq FROM sqlite_sequence;
- name
- O nome da tabela que tem
AUTOINCREMENT. - seq
- O maior id que essa tabela já teve. O cupom 3 foi apagado, mas o
seqcontinua 3: é por isso que o próximo será o 4.
No banco limpo da Loja Aurora, essa tabela não existe, porque nenhuma tabela da loja usa AUTOINCREMENT. Tente SELECT * FROM sqlite_sequence; sozinho e o SQLite responde no such table: sqlite_sequence ("não existe a tabela sqlite_sequence").
No terminal do sqlite3, a Ana pode ver que a tabela foi criada, com um detalhe: o comando .tables esconde as tabelas internas, cujos nomes começam com sqlite_. Para vê-la, é preciso pedir pelo nome:
$ sqlite3 loja.db
SQLite version 3.50.4 2025-07-30 19:33:53
Enter ".help" for usage hints.
sqlite> CREATE TABLE cupons (id INTEGER PRIMARY KEY AUTOINCREMENT, codigo TEXT NOT NULL);
sqlite> .tables
categorias cupons funcionarios pedidos
clientes fornecedores itens_pedido produtos
sqlite> .schema sqlite_sequence
CREATE TABLE sqlite_sequence(name,seq);
sqlite> INSERT INTO cupons (codigo) VALUES ('BEMVINDO');
sqlite> SELECT * FROM sqlite_sequence;
cupons|1
sqlite> .quit
Dá para mudar a sqlite_sequence com UPDATE e DELETE comuns, e alguns tutoriais ensinam isso para "zerar o contador". A documentação do SQLite avisa que mexer nela "provavelmente vai bagunçar" o algoritmo do AUTOINCREMENT. Se você zerar o contador com cupons ainda na tabela, o próximo id pode bater num que já existe. E zerar o contador desfaz justamente a garantia que fez você escolher AUTOINCREMENT.
Mesmo esvaziando a tabela, a conta continua
Aqui a diferença entre os dois jeitos fica mais clara. A Ana apaga todos os cupons e cria um novo:
CREATE TABLE cupons (
id INTEGER PRIMARY KEY AUTOINCREMENT,
codigo TEXT NOT NULL,
desconto REAL NOT NULL
);
INSERT INTO cupons (codigo, desconto)
VALUES ('BEMVINDO', 10), ('NATAL', 15), ('PIAUI', 5);
DELETE FROM cupons;
INSERT INTO cupons (codigo, desconto) VALUES ('VERAO', 20);
SELECT * FROM cupons;
Com AUTOINCREMENT, o VERAO é o 4. Agora a mesma coisa sem AUTOINCREMENT:
CREATE TABLE cupons (
id INTEGER PRIMARY KEY,
codigo TEXT NOT NULL,
desconto REAL NOT NULL
);
INSERT INTO cupons (codigo, desconto)
VALUES ('BEMVINDO', 10), ('NATAL', 15), ('PIAUI', 5);
DELETE FROM cupons;
INSERT INTO cupons (codigo, desconto) VALUES ('VERAO', 20);
SELECT * FROM cupons;
Sem AUTOINCREMENT, a tabela vazia recomeça do 1: o maior id de uma tabela vazia é "nenhum", e a primeira linha ganha 1.
E se você digitar o id?
Você sempre pode escolher o número na mão. Nos dois jeitos, o número seguinte continua a partir do maior:
CREATE TABLE cupons (
id INTEGER PRIMARY KEY AUTOINCREMENT,
codigo TEXT NOT NULL,
desconto REAL NOT NULL
);
INSERT INTO cupons (id, codigo, desconto) VALUES (100, 'BEMVINDO', 10);
INSERT INTO cupons (codigo, desconto) VALUES ('NATAL', 15);
SELECT * FROM cupons;
SELECT name, seq FROM sqlite_sequence;
O NATAL ganhou o 101, e a sqlite_sequence anotou 101. Isso é útil para "começar a numeração do 100": insira a primeira linha com o id 100 e deixe o banco seguir dali.
4. Então devo usar AUTOINCREMENT sempre?
Não. A própria documentação do SQLite diz que o AUTOINCREMENT "gasta mais processador, memória, espaço em disco e acesso ao disco, e deve ser evitado se não for estritamente necessário. Normalmente, não é necessário." A cada INSERT, o banco precisa ler e atualizar a sqlite_sequence. Repare que as sete tabelas da Loja Aurora usam só INTEGER PRIMARY KEY.
E um detalhe que confunde: o AUTOINCREMENT garante que os números crescem e nunca voltam, mas não garante que vêm em sequência sem buracos: cada linha apagada deixa um buraco para sempre, e um id digitado na mão (como o 100 da seção anterior) pula todos os números do meio. Se você precisa de "nota fiscal 1, 2, 3, sem pular nenhuma", isso é regra do seu sistema, não do AUTOINCREMENT.
| Situação | Use | Por quê |
|---|---|---|
| Quase todas as tabelas (clientes, produtos, pedidos…) | INTEGER PRIMARY KEY | Numera sozinho, é o mais rápido, e reaproveitar o último número não atrapalha. |
| O número vai para fora do banco e não pode nunca apontar para outra coisa (cupom impresso, protocolo de atendimento, número enviado a outro sistema) | INTEGER PRIMARY KEY AUTOINCREMENT | Um número apagado nunca volta, nem se a tabela for esvaziada. |
| O número já vem de fora (código de barras, CPF, código do fornecedor) | Chave que você mesmo informa | Não precisa numeração automática; veja PRIMARY KEY. |
| Uma tabela sem nenhuma chave declarada | O rowid escondido | Ele existe e numera sozinho, mas não aparece no SELECT *. Prefira declarar o id: deixa a tabela clara para quem lê. |
Quando dá errado
A Ana escreveu INT em vez de INTEGER:
CREATE TABLE cupons (
id INT PRIMARY KEY AUTOINCREMENT,
codigo TEXT NOT NULL
);
A mensagem: AUTOINCREMENT is only allowed on an INTEGER PRIMARY KEY, "o AUTOINCREMENT só é permitido numa INTEGER PRIMARY KEY". O SQLite exige o tipo escrito exatamente INTEGER. O mesmo erro aparece com TEXT PRIMARY KEY AUTOINCREMENT.
Como consertar: id INTEGER PRIMARY KEY AUTOINCREMENT.
CREATE TABLE cupons (
id INTEGER AUTOINCREMENT,
codigo TEXT NOT NULL
);
A mensagem: near "AUTOINCREMENT": syntax error, "erro de sintaxe perto de AUTOINCREMENT". Para o SQLite, AUTOINCREMENT é um pedaço do PRIMARY KEY; sozinho, ele não faz sentido.
Como consertar: escreva as três partes juntas, nesta ordem: INTEGER PRIMARY KEY AUTOINCREMENT.
Quem vem do MySQL escreve com sublinhado:
CREATE TABLE cupons (
id INTEGER PRIMARY KEY AUTO_INCREMENT,
codigo TEXT NOT NULL
);
A mensagem: near "AUTO_INCREMENT": syntax error. No SQLite a palavra é AUTOINCREMENT, junta e sem sublinhado.
Como consertar: tire o sublinhado, ou tire a palavra inteira: na maioria dos casos o INTEGER PRIMARY KEY sozinho já basta.
Este é o pior, porque não dá erro. A Ana criou a tabela de recados com INT no lugar de INTEGER, e sem AUTOINCREMENT:
CREATE TABLE recados (
id INT PRIMARY KEY,
texto TEXT
);
INSERT INTO recados (texto)
VALUES ('Repor lápis'), ('Ligar para o fornecedor');
SELECT * FROM recados;
O que aconteceu: os dois recados ficaram com o id NULL. Só a escrita exata INTEGER PRIMARY KEY faz a coluna virar o rowid e se numerar sozinha. Com INT, ela é uma coluna comum que, por um defeito antigo que o SQLite mantém por compatibilidade, ainda aceita NULL mesmo sendo chave primária. O mesmo acontece com id SERIAL PRIMARY KEY, a forma do PostgreSQL: o SQLite aceita o nome SERIAL como tipo, mas ele não numera nada.
Como consertar: id INTEGER PRIMARY KEY. Se você quer se proteger também do NULL, a aula NOT NULL mostra como.
Missão: rode o código e veja os ids vazios. Conserte a criação da tabela para que os recados ganhem os números 1 e 2 sozinhos. Não mude o INSERT.
CREATE TABLE recados (
id INT PRIMARY KEY,
texto TEXT
);
INSERT INTO recados (texto)
VALUES ('Repor lápis'), ('Ligar para o fornecedor');
SELECT * FROM recados;
CREATE TABLE recados (
id INTEGER PRIMARY KEY,
texto TEXT
);
INSERT INTO recados (texto)
VALUES ('Repor lápis'), ('Ligar para o fornecedor');
SELECT * FROM recados;
INSERT INTO clientes (id, nome) VALUES (5, 'Rita Moura');
A mensagem: UNIQUE constraint failed: clientes.id, "a regra de valor único falhou em clientes.id". O cliente 5 é a Conceição Prado. Numeração automática não impede você de digitar um número repetido na mão; quem impede é a chave primária, que não aceita dois iguais.
Como consertar: não informe o id e deixe o banco escolher.
O maior número que cabe num INTEGER do SQLite é 9223372036854775807 (mais de 9 quintilhões). Se ele já foi usado numa tabela com AUTOINCREMENT, não existe "próximo":
CREATE TABLE cupons (
id INTEGER PRIMARY KEY AUTOINCREMENT,
codigo TEXT
);
INSERT INTO cupons (id, codigo) VALUES (9223372036854775807, 'MAX');
INSERT INTO cupons (codigo) VALUES ('X');
A mensagem: database or disk is full, "o banco ou o disco está cheio". O disco não está cheio: o SQLite usa esse erro para dizer que não há mais número disponível. Na vida real ninguém chega lá contando de 1 em 1; isso só acontece quando alguém digita um id gigante na mão. Sem AUTOINCREMENT, o SQLite ainda tenta sortear um número livre antes de desistir.
Cada banco tem o seu jeito de numerar sozinho. Os trechos abaixo são ilustrativos: não rodam no SQLite.
-- MySQL e MariaDB: AUTO_INCREMENT (com sublinhado)
CREATE TABLE cupons (
id INT NOT NULL AUTO_INCREMENT,
codigo VARCHAR(20) NOT NULL,
PRIMARY KEY (id)
);
SELECT LAST_INSERT_ID(); -- o último número gerado
-- PostgreSQL: a forma do padrão SQL
CREATE TABLE cupons (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
codigo text NOT NULL
);
-- forma antiga, ainda muito vista: id serial PRIMARY KEY
-- SQL Server: IDENTITY(início, passo)
CREATE TABLE cupons (
id INT IDENTITY(1, 1) PRIMARY KEY,
codigo VARCHAR(20) NOT NULL
);
As documentações do SQL Server e do PostgreSQL avisam que um número já gerado não é reaproveitado e que pode haver buracos na sequência, mesmo sem apagar nada (um INSERT que falha também "gasta" o número). É o comportamento do AUTOINCREMENT do SQLite, não o do INTEGER PRIMARY KEY simples. No PostgreSQL, o serial é, segundo a documentação, "uma conveniência de escrita": cria um contador (sequence) e põe o próximo número dele como valor padrão da coluna. O GENERATED ALWAYS recusa um id digitado na mão, a não ser que o INSERT peça isso explicitamente; o GENERATED BY DEFAULT aceita.
Referência rápida
| Escrita | O que faz |
|---|---|
id INTEGER PRIMARY KEY | Vira o rowid e numera sozinho: "o maior + 1". O último número pode ser reaproveitado. |
id INTEGER PRIMARY KEY AUTOINCREMENT | Numera sozinho e nunca reaproveita: sempre maior que todos os que já existiram. |
INSERT sem o id, ou com id = NULL | Pede ao banco para escolher o número. |
INSERT com id = 100 | Usa o 100; os próximos seguem a partir dele. |
SELECT last_insert_rowid(); | O número que a última linha inserida ganhou. |
SELECT * FROM sqlite_sequence; | O maior id que cada tabela com AUTOINCREMENT já teve. Só existe depois da primeira tabela com AUTOINCREMENT. |
rowid | O número escondido de toda linha de uma tabela comum. |
| Mensagem | Quer dizer |
|---|---|
AUTOINCREMENT is only allowed on an INTEGER PRIMARY KEY | O tipo não é exatamente INTEGER (ex.: INT, TEXT). |
near "AUTOINCREMENT": syntax error | AUTOINCREMENT fora do PRIMARY KEY. |
near "AUTO_INCREMENT": syntax error | Escrita do MySQL; no SQLite é AUTOINCREMENT. |
UNIQUE constraint failed: clientes.id | Você digitou um id que já existe. |
no such table: sqlite_sequence | Nenhuma tabela deste banco usa AUTOINCREMENT ainda. |
database or disk is full | Com AUTOINCREMENT: o maior número possível já foi usado. |
Exercícios
1. A palavra certa
Complete para que um id apagado nunca seja reaproveitado:
2. A tabela da conta
Complete o nome da tabela interna onde o SQLite guarda o maior id de cada tabela com AUTOINCREMENT:
3. A tabela clientes (com id INTEGER PRIMARY KEY, sem AUTOINCREMENT) tem os ids de 1 a 30. A Ana apaga o cliente 30 e cadastra um novo sem informar o id. Que número ele ganha?
4. E se a tabela fosse a de cupons, com AUTOINCREMENT, com os ids de 1 a 3, e a Ana apagasse todos os cupons antes de criar um novo?
5. A Ana criou uma tabela com id INT PRIMARY KEY e inseriu linhas sem informar o id. O que aparece na coluna id?
6. Por que a documentação do SQLite recomenda evitar o AUTOINCREMENT quando ele não é necessário?
Missão final: o cupom que não pode voltar
Missão: o código cria os cupons, cancela o cupom 3 e cria o VERAO. Rode e veja: o VERAO ganhou o número 3, o mesmo do cupom cancelado. Mude só a criação da tabela para que o VERAO ganhe o 4 sozinho, sem digitar o id no INSERT. Se quiser, acrescente no fim um SELECT na sqlite_sequence para ver a conta.
CREATE TABLE cupons (
id INTEGER PRIMARY KEY,
codigo TEXT NOT NULL,
desconto REAL NOT NULL
);
INSERT INTO cupons (codigo, desconto)
VALUES ('BEMVINDO', 10), ('NATAL', 15), ('PIAUI', 5);
DELETE FROM cupons WHERE id = 3;
INSERT INTO cupons (codigo, desconto) VALUES ('VERAO', 20);
SELECT * FROM cupons;
CREATE TABLE cupons (
id INTEGER PRIMARY KEY AUTOINCREMENT,
codigo TEXT NOT NULL,
desconto REAL NOT NULL
);
INSERT INTO cupons (codigo, desconto)
VALUES ('BEMVINDO', 10), ('NATAL', 15), ('PIAUI', 5);
DELETE FROM cupons WHERE id = 3;
INSERT INTO cupons (codigo, desconto) VALUES ('VERAO', 20);
SELECT * FROM cupons;
SELECT name, seq FROM sqlite_sequence;
Resumo
- No SQLite, uma coluna
INTEGER PRIMARY KEYé outro nome para orowide já numera sozinha: deixe o id fora doINSERT(ou mandeNULL) e ela ganha "o maior + 1". - Sem
AUTOINCREMENT, o número do último registro apagado pode voltar, e uma tabela esvaziada recomeça do 1. - Com
INTEGER PRIMARY KEY AUTOINCREMENT, o número novo é sempre maior que todos os que já existiram. A conta fica na tabela internasqlite_sequence. AUTOINCREMENTcusta um pouco a cadaINSERT: use só quando um número reaproveitado causaria confusão fora do banco.- A escrita tem de ser exata:
INTEGER, nãoINT;AUTOINCREMENT, nãoAUTO_INCREMENT. ComINT PRIMARY KEY, o id fica NULL sem erro nenhum. last_insert_rowid()diz o número que a última linha ganhou. Nos outros bancos:AUTO_INCREMENT(MySQL),GENERATED … AS IDENTITYouserial(PostgreSQL),IDENTITY(1, 1)(SQL Server).