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.

Você vai aprender
  • O que é uma restrição (constraint) e onde ela se escreve no CREATE TABLE.
  • Como o NOT NULL recusa um INSERT que esquece a coluna, ou que manda NULL de propósito, e também um UPDATE.
  • A mensagem real: NOT NULL constraint failed: tabela.coluna.
  • Por que o texto vazio '' passa pelo NOT NULL, e como barrá-lo também.
  • Como o NOT NULL trabalha junto com o DEFAULT, e o erro de acrescentar uma coluna NOT NULL numa 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árioNa 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 DEFAULT tem 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, coluna nome, 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

FormaExemploQuando usar
NOT NULL depois do tiponome TEXT NOT NULLSempre: é a forma comum, igual em todos os bancos
NOT NULL com DEFAULTvip INTEGER NOT NULL DEFAULT 0Colunas obrigatórias que têm um valor "normal" (estoque 0, não VIP)
NOT NULL com CHECKnome TEXT NOT NULL CHECK (trim(nome) <> '')Quando o texto vazio também é proibido
NULL escritoemail TEXT NULLOpcional: deixa claro que a coluna aceita vazio. O SQLite aceita a palavra; o efeito é o mesmo de não escrever nada
Sem nadaemail TEXTA coluna aceita NULL (é o padrão)
Quais colunas devem ser 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

Esqueceu uma coluna obrigatória no 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.

Mandou 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).

O 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) = '';.

Aspas duplas no texto
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'.

Acrescentar coluna obrigatória sem padrão

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.

Nos outros bancos

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

EscritaO que faz
coluna TIPO NOT NULLA coluna não aceita NULL (no INSERT e no UPDATE)
coluna TIPO NOT NULL DEFAULT valorObrigató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 SQLiteQuer dizer
NOT NULL constraint failed: clientes.nomeA 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 NULLALTER TABLE … ADD COLUMN … NOT NULL sem DEFAULT

Exercícios

1. Nome obrigatório

Complete para que toda marca tenha nome:

CREATE TABLE marcas (id INTEGER, nome TEXT );

2. A mensagem

O INSERT INTO avaliacoes (id, nota) VALUES (1, 5); esqueceu o produto_id, que é NOT NULL. Complete a mensagem do SQLite:

NOT NULL constraint failed:

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íbe NULL na coluna.
  • Vale no INSERT (coluna esquecida ou NULL de propósito) e no UPDATE. O erro real é NOT NULL constraint failed: tabela.coluna; no terminal, Runtime error: … (19).
  • Se uma linha de um INSERT com várias linhas falha, nenhuma entra.
  • Texto vazio '' não é NULL e passa. Para barrá-lo, junte CHECK (trim(nome) <> '').
  • Com DEFAULT, a coluna esquecida ganha o valor padrão; mas NULL escrito de propósito continua recusado.
  • Para acrescentar uma coluna NOT NULL numa tabela com dados, ela precisa de um DEFAULT.