SQL NOT NULL
Um cliente sem email, tudo bem: na Loja Aurora há três assim. Mas um cliente sem nome? Uma avaliação sem nota? Isso não faz sentido, e o banco pode impedir que aconteça. A regra que faz isso é o NOT NULL ("não nulo"): escrita no CREATE TABLE, ela proíbe que a coluna fique vazia. Nesta aula você vai usá-la, vai ver a mensagem real que o SQLite dá quando alguém tenta deixar a coluna vazia e vai conhecer a pegadinha do texto vazio, que não é NULL.
- O que é uma restrição (constraint) e onde ela se escreve no
CREATE TABLE. - Como o
NOT NULLrecusa umINSERTque esquece a coluna, ou que mandaNULLde propósito, e também umUPDATE. - A mensagem real:
NOT NULL constraint failed: tabela.coluna. - Por que o texto vazio
''passa peloNOT NULL, e como barrá-lo também. - Como o
NOT NULLtrabalha junto com oDEFAULT, e o erro de acrescentar uma colunaNOT NULLnuma tabela que já tem dados.
Se o NULL ainda está nebuloso, reveja antes a aula O Valor NULL: NULL é a ausência de valor, o "não sei" ou "não informado".
A ideia: o campo obrigatório
Todo formulário da internet tem aquele asterisco vermelho: Nome*. Campo obrigatório. Se você tenta enviar o formulário com ele em branco, a página recusa e mostra "Preencha este campo". Os outros campos, sem asterisco, podem ficar em branco.
O NOT NULL é o asterisco da coluna. A diferença é que quem confere não é a página: é o próprio banco, a cada INSERT e a cada UPDATE. Não importa se o dado veio de um site, de um aplicativo ou de alguém digitando SQL no terminal; nenhum caminho deixa a coluna vazia.
| No formulário | Na tabela |
|---|---|
| Campo com asterisco (obrigatório) | Coluna com NOT NULL |
| Campo sem asterisco (opcional) | Coluna sem NOT NULL: aceita NULL |
| "Preencha este campo" | NOT NULL constraint failed: … |
1. A Loja Aurora já usa NOT NULL
Olhe de novo como foi criada a tabela clientes:
SELECT sql FROM sqlite_schema WHERE name = 'clientes';
- nome TEXT NOT NULL
- O nome é obrigatório. Todo cliente tem nome.
- email TEXT
- Sem
NOT NULL: o email é opcional. É por isso que os clientes 7, 15 e 23 podem estar sem email. - cidade, estado, nascimento
- Também opcionais.
- vip INTEGER NOT NULL DEFAULT 0
- Obrigatório, mas com um valor padrão: se ninguém disser, vale 0. O
DEFAULTtem aula própria: DEFAULT.
O NOT NULL é uma restrição (em inglês, constraint): uma regra presa à coluna, que o banco confere sozinho. Ela vem depois do tipo, na mesma linha da coluna. A forma geral é:
nome_da_coluna TIPO NOT NULL
Para ver de uma vez quais colunas são obrigatórias, use o PRAGMA table_info (aula CREATE TABLE): a coluna notnull do resultado vale 1 nas obrigatórias.
SELECT name, type, "notnull" FROM pragma_table_info('produtos');
Em produtos, só o id aparece com 0, e mesmo ele nunca fica vazio, por ser a chave primária (aula PRIMARY KEY). Repare nas aspas duplas em "notnull": NOTNULL também é uma palavra do SQLite, e as aspas duplas avisam que ali é o nome de uma coluna (sem elas, dá near "notnull": syntax error).
2. Quando o INSERT esquece a coluna
Uma cliente nova se cadastrou, mas o sistema esqueceu de mandar o nome:
INSERT INTO clientes (email, cidade, estado)
VALUES ('rita@exemplo.com.br', 'Teresina', 'PI');
- NOT NULL constraint failed
- "A restrição NOT NULL falhou": a regra de "não pode ficar vazio" foi quebrada.
- clientes.nome
- Onde: tabela
clientes, colunanome, separadas por ponto.
A coluna nome não estava na lista do INSERT. Uma coluna que fica de fora recebe o seu valor padrão, e o valor padrão de uma coluna sem DEFAULT é NULL. NULL numa coluna NOT NULL: recusado. A linha não entra, e a tabela continua com os 30 clientes.
Mandar NULL de propósito dá o mesmo erro:
INSERT INTO clientes (nome, email) VALUES (NULL, 'rita@exemplo.com.br');
Com o nome, entra. As colunas opcionais que ficaram de fora viram NULL, e o vip, que tem DEFAULT 0, ganha 0:
INSERT INTO clientes (nome, email, cidade, estado)
VALUES ('Rita Moura', 'rita@exemplo.com.br', 'Teresina', 'PI');
SELECT * FROM clientes WHERE id = 31;
Experimente: o cadastro do Caio deu erro. Rode, leia a mensagem e conserte o INSERT para que ele entre na tabela (o nome dele é Caio Freitas).
INSERT INTO clientes (email, cidade, estado)
VALUES ('caio.freitas@exemplo.com.br', 'Parnaíba', 'PI');
SELECT * FROM clientes WHERE id = 31;
INSERT INTO clientes (nome, email, cidade, estado)
VALUES ('Caio Freitas', 'caio.freitas@exemplo.com.br', 'Parnaíba', 'PI');
SELECT * FROM clientes WHERE id = 31;
3. Também vale no UPDATE
O NOT NULL não protege só a entrada. Se alguém tenta "apagar" o nome de um cliente que já existe, o banco recusa do mesmo jeito:
UPDATE clientes SET nome = NULL WHERE id = 5;
Já o email, que é opcional, pode ser apagado à vontade (aula UPDATE):
UPDATE clientes SET email = NULL WHERE id = 5; SELECT nome, email FROM clientes WHERE id = 5;
4. Criar uma tabela com NOT NULL
Na tabela de avaliações, quais colunas são obrigatórias? Uma avaliação tem de dizer qual produto e qual nota. O comentário é opcional: muita gente só dá as estrelinhas.
CREATE TABLE avaliacoes (
id INTEGER,
produto_id INTEGER NOT NULL,
nota INTEGER NOT NULL,
comentario TEXT
);
INSERT INTO avaliacoes (id, produto_id, nota)
VALUES (1, 3, 5);
INSERT INTO avaliacoes (id, produto_id, comentario)
VALUES (2, 3, 'Chegou rápido');
O primeiro INSERT entrou ("1 linha afetada"): tem produto e nota, e o comentário ficou NULL, o que é permitido. O segundo foi recusado: NOT NULL constraint failed: avaliacoes.nota, porque esqueceu a nota.
No terminal, a mensagem é a mesma, com o prefixo Runtime error: e o código (19) no fim (19 é o número que o SQLite usa para "uma restrição foi violada"):
$ sqlite3 loja.db SQLite version 3.50.4 2025-07-30 19:33:53 Enter ".help" for usage hints. sqlite> CREATE TABLE avaliacoes (id INTEGER, produto_id INTEGER NOT NULL, nota INTEGER NOT NULL, comentario TEXT); sqlite> INSERT INTO avaliacoes (id, produto_id, comentario) VALUES (1, 3, 'Chegou rápido'); Runtime error: NOT NULL constraint failed: avaliacoes.nota (19) sqlite> .quit
Experimente: esta tabela aceita uma avaliação sem nota (rode e veja o NULL na coluna nota). Mude o CREATE TABLE para que o banco recuse esse INSERT. Aqui, o erro em vermelho é a resposta certa.
CREATE TABLE avaliacoes (
id INTEGER,
produto_id INTEGER,
nota INTEGER,
comentario TEXT
);
INSERT INTO avaliacoes (id, produto_id, comentario)
VALUES (1, 3, 'Chegou rápido');
SELECT * FROM avaliacoes;
CREATE TABLE avaliacoes (
id INTEGER,
produto_id INTEGER,
nota INTEGER NOT NULL,
comentario TEXT
);
INSERT INTO avaliacoes (id, produto_id, comentario)
VALUES (1, 3, 'Chegou rápido');
SELECT * FROM avaliacoes;
Várias linhas: uma ruim derruba todas
Um INSERT com várias linhas (aula Inserindo Várias Linhas) é um comando só. Se uma das linhas quebra a regra, o comando inteiro é recusado e nenhuma entra, nem as boas. A Ana conferiu no terminal:
$ sqlite3 loja.db SQLite version 3.50.4 2025-07-30 19:33:53 Enter ".help" for usage hints. sqlite> CREATE TABLE avaliacoes (id INTEGER, produto_id INTEGER NOT NULL, nota INTEGER NOT NULL, comentario TEXT); sqlite> INSERT INTO avaliacoes (id, produto_id, nota) VALUES (1, 3, 5), (2, 3, NULL), (3, 1, 4); Runtime error: NOT NULL constraint failed: avaliacoes.nota (19) sqlite> SELECT count(*) FROM avaliacoes; 0 « nem a linha 1 nem a 3 entraram sqlite> .quit
Isso é bom: você nunca fica com metade de um lote gravado e a outra metade perdida. Conserte a linha ruim e rode o lote de novo.
5. A pegadinha: texto vazio não é NULL
O NOT NULL recusa NULL, e só NULL. Um texto vazio, '' (duas aspas simples sem nada no meio), é um texto de verdade, com zero letras. Ele passa:
INSERT INTO clientes (nome) VALUES ('');
SELECT id, nome, length(nome) AS letras, nome IS NULL AS e_nulo
FROM clientes
WHERE id = 31;
A cliente 31 entrou com um nome de zero letras, e nome IS NULL deu 0 ("falso"). Para o banco, a regra foi cumprida. Do mesmo jeito, passam um nome feito só de espaços (' ') e até o texto 'NULL', entre aspas, que é só uma palavra de quatro letras.
Para barrar também o texto vazio, junte ao NOT NULL uma regra CHECK (aula CHECK):
CREATE TABLE contatos (
nome TEXT NOT NULL CHECK (trim(nome) <> '')
);
INSERT INTO contatos (nome) VALUES (' ');
- NOT NULL
- Barra o
NULL. - CHECK ( … )
- "Confira": o valor só entra se a condição for verdadeira.
- trim(nome) <> ''
trim()tira os espaços das pontas (aula Funções de Texto); o que sobra tem de ser diferente (<>) de vazio. Barra''e' '.
6. NOT NULL junto com DEFAULT
Na tabela produtos, o estoque é INTEGER NOT NULL DEFAULT 0. As duas regras se completam: se o INSERT não falar do estoque, entra 0, e a coluna nunca fica vazia.
INSERT INTO produtos (nome, categoria_id, fornecedor_id, preco)
VALUES ('Régua 30 cm', 1, 1, 3.5);
SELECT * FROM produtos WHERE id = 46;
Mas o DEFAULT só entra quando a coluna é deixada de fora. Mandar NULL de propósito não aciona o padrão: o NOT NULL recusa.
INSERT INTO produtos (nome, categoria_id, fornecedor_id, preco, estoque)
VALUES ('Régua 30 cm', 1, 1, 3.5, NULL);
E quando faltam várias colunas obrigatórias, o SQLite avisa uma por vez: a primeira que ele encontra, na ordem do CREATE TABLE. Conserte essa, rode de novo, e ele mostra a próxima.
INSERT INTO produtos (nome) VALUES ('Régua 30 cm');
Aqui faltam categoria_id, fornecedor_id e preco, mas a mensagem fala só de categoria_id, a primeira delas.
7. NOT NULL numa tabela que já tem dados
A Ana quer acrescentar o telefone dos clientes, obrigatório, com ALTER TABLE (aula ALTER TABLE):
ALTER TABLE clientes ADD COLUMN telefone TEXT NOT NULL;
"Não é possível acrescentar uma coluna NOT NULL com valor padrão NULL." Faz sentido: a tabela já tem 30 clientes. Que telefone eles teriam na coluna nova? Sem DEFAULT, seria NULL, e isso a própria regra proíbe. A saída é dar um valor padrão:
ALTER TABLE clientes ADD COLUMN telefone TEXT NOT NULL DEFAULT ''; SELECT id, nome, telefone FROM clientes LIMIT 3;
Funcionou, mas repare: os 30 clientes ganharam um telefone '', vazio. Isso é o mesmo que não ter telefone, só que disfarçado. Muitas vezes é melhor deixar a coluna opcional e preencher aos poucos.
Formas diferentes de escrever
| Forma | Exemplo | Quando usar |
|---|---|---|
NOT NULL depois do tipo | nome TEXT NOT NULL | Sempre: é a forma comum, igual em todos os bancos |
NOT NULL com DEFAULT | vip INTEGER NOT NULL DEFAULT 0 | Colunas obrigatórias que têm um valor "normal" (estoque 0, não VIP) |
NOT NULL com CHECK | nome TEXT NOT NULL CHECK (trim(nome) <> '') | Quando o texto vazio também é proibido |
NULL escrito | email TEXT NULL | Opcional: deixa claro que a coluna aceita vazio. O SQLite aceita a palavra; o efeito é o mesmo de não escrever nada |
| Sem nada | email TEXT | A coluna aceita NULL (é o padrão) |
NOT NULL?
Pergunte: "uma linha sem este dado faz sentido?". Um pedido sem cliente, não: cliente_id NOT NULL. Um pedido sem data de entrega, sim, enquanto ele não foi entregue: entregue_em fica opcional. Na dúvida, comece com NOT NULL: é fácil afrouxar a regra depois, e difícil limpar uma tabela cheia de buracos.
Quando dá errado
INSERT
INSERT INTO produtos (nome, categoria_id, fornecedor_id)
VALUES ('Régua 30 cm', 1, 1);
O que diz: NOT NULL constraint failed: produtos.preco. Como consertar: ponha a coluna da mensagem na lista do INSERT, com um valor. Se faltarem outras, o SQLite mostra a próxima quando você rodar de novo.
NULL achando que o DEFAULT ia entrar
INSERT … (…, estoque) VALUES (…, NULL) dá NOT NULL constraint failed: produtos.estoque, mesmo com DEFAULT 0. Como consertar: para usar o padrão, tire a coluna da lista (ou escreva o valor, 0).
NOT NULL "deixou passar" um nome vazio
Não deixou: '' não é NULL. Como consertar: junte CHECK (trim(nome) <> '') à coluna. Para achar os vazios que já estão na tabela: SELECT * FROM clientes WHERE trim(nome) = '';.
INSERT INTO clientes (nome, email)
VALUES ('Rita Moura', "rita@exemplo.com.br");
O que diz: no such column: "rita@exemplo.com.br" - should this be a string literal in single-quotes?, "não existe a coluna…: isto deveria ser um texto entre aspas simples?". Não é um erro do NOT NULL, mas aparece muito num INSERT: aspas duplas marcam nomes de coluna. Como consertar: texto vai entre aspas simples: 'rita@exemplo.com.br'.
ALTER TABLE clientes ADD COLUMN telefone TEXT NOT NULL; dá Cannot add a NOT NULL column with default value NULL. Como consertar: dê um DEFAULT à coluna, ou crie-a opcional.
NOT NULL é do SQL padrão e se escreve igual no MySQL, no PostgreSQL e no SQL Server: nome VARCHAR(100) NOT NULL. O que muda é o texto da mensagem de erro, que cada banco escreve do seu jeito, mas todos recusam a linha. Lembre que o NOT NULL só cuida do vazio: quem barra um texto numa coluna de número é o tipo, que nos outros bancos é sempre conferido e, no SQLite, só numa tabela STRICT (aula Os Tipos no SQLite).
Referência rápida
| Escrita | O que faz |
|---|---|
coluna TIPO NOT NULL | A coluna não aceita NULL (no INSERT e no UPDATE) |
coluna TIPO NOT NULL DEFAULT valor | Obrigatória, com valor automático quando fica fora do INSERT |
coluna TEXT NOT NULL CHECK (trim(coluna) <> '') | Barra também o texto vazio e o só de espaços |
SELECT name, "notnull" FROM pragma_table_info('t'); | Mostra quais colunas são obrigatórias (1) |
| Mensagem do SQLite | Quer dizer |
|---|---|
NOT NULL constraint failed: clientes.nome | A coluna nome de clientes ficou vazia (esquecida ou NULL) |
Runtime error: NOT NULL constraint failed: … (19) | O mesmo, no terminal sqlite3 |
Cannot add a NOT NULL column with default value NULL | ALTER TABLE … ADD COLUMN … NOT NULL sem DEFAULT |
Exercícios
1. Nome obrigatório
Complete para que toda marca tenha nome:
2. A mensagem
O INSERT INTO avaliacoes (id, nota) VALUES (1, 5); esqueceu o produto_id, que é NOT NULL. Complete a mensagem do SQLite:
3. A coluna nome é TEXT NOT NULL. Qual destes valores é recusado?
4. Um INSERT com três linhas tem uma delas com NULL numa coluna NOT NULL. Quantas linhas entram?
5. A coluna é estoque INTEGER NOT NULL DEFAULT 0. O que acontece com INSERT INTO produtos (…, estoque) VALUES (…, NULL)?
6. Na tabela pedidos, qual coluna não deveria ser NOT NULL?
Missão final: a tabela de avaliações
Missão: deixe obrigatórias as colunas produto_id e nota da tabela de avaliações. O comentario continua opcional, e as duas avaliações abaixo (uma delas sem comentário) têm de continuar entrando. O PRAGMA no fim mostra o 1 nas colunas obrigatórias.
CREATE TABLE avaliacoes (
id INTEGER,
produto_id INTEGER,
nota INTEGER,
comentario TEXT
);
INSERT INTO avaliacoes (id, produto_id, nota, comentario)
VALUES (1, 3, 5, 'Chegou rápido');
INSERT INTO avaliacoes (id, produto_id, nota)
VALUES (2, 1, 4);
PRAGMA table_info(avaliacoes);
CREATE TABLE avaliacoes (
id INTEGER,
produto_id INTEGER NOT NULL,
nota INTEGER NOT NULL,
comentario TEXT
);
INSERT INTO avaliacoes (id, produto_id, nota, comentario)
VALUES (1, 3, 5, 'Chegou rápido');
INSERT INTO avaliacoes (id, produto_id, nota)
VALUES (2, 1, 4);
PRAGMA table_info(avaliacoes);
Quer ir além? Acrescente no fim um terceiro INSERT, sem a nota, e veja a mensagem. Depois apague-o: a missão pede que as duas avaliações boas entrem.
Resumo
NOT NULLé uma restrição: escrita depois do tipo (nome TEXT NOT NULL), ela proíbeNULLna coluna.- Vale no
INSERT(coluna esquecida ouNULLde propósito) e noUPDATE. O erro real éNOT NULL constraint failed: tabela.coluna; no terminal,Runtime error: … (19). - Se uma linha de um
INSERTcom várias linhas falha, nenhuma entra. - Texto vazio
''não éNULLe passa. Para barrá-lo, junteCHECK (trim(nome) <> ''). - Com
DEFAULT, a coluna esquecida ganha o valor padrão; masNULLescrito de propósito continua recusado. - Para acrescentar uma coluna
NOT NULLnuma tabela com dados, ela precisa de umDEFAULT.