SQL DEFAULT
Quando a Loja Aurora cadastra um produto novo e ninguém diz quantos há no estoque, o estoque começa em 0. Quando entra um cliente novo, ele começa como não VIP. Ninguém precisa escrever isso em cada INSERT: o banco preenche sozinho. Quem faz isso é o DEFAULT ("padrão"), a restrição que dá a uma coluna um valor padrão, usado sempre que o INSERT deixa a coluna de fora. Nesta aula você vai criar valores padrão com números, textos e a data de hoje, e vai ver quando o padrão não entra, que é onde mora a confusão.
- Como escrever
DEFAULT valornoCREATE TABLE, e quando o banco usa esse valor. - Os tipos de valor padrão: número, texto,
NULL, e as palavrasCURRENT_DATE,CURRENT_TIMEeCURRENT_TIMESTAMP. - Valores padrão calculados, com uma expressão entre parênteses.
- O
INSERT … DEFAULT VALUES, que cria uma linha só com os padrões. - A dupla
NOT NULL DEFAULT, e oDEFAULTnoALTER TABLE. - Os erros reais: padrão sem parênteses, padrão que olha outra coluna,
NULLque não vira padrão.
A ideia: o formulário já preenchido
Sabe aquele formulário em que o campo "País" já vem marcado com Brasil? Você pode trocar, mas, se não mexer, vai Brasil. E o campo "Quantidade" do carrinho de compras, que já vem com 1? É a mesma ideia: um valor que vale quando ninguém diz outro.
| No formulário | Na tabela |
|---|---|
| "País" já vem com Brasil | pais TEXT DEFAULT 'Brasil' |
| "Quantidade" já vem com 1 | quantidade INTEGER DEFAULT 1 |
| A pessoa troca o valor | O INSERT informa a coluna: vale o que ele mandou |
| A pessoa não mexe | O INSERT deixa a coluna de fora: vale o DEFAULT |
Sem DEFAULT, a coluna esquecida fica com NULL. Na verdade, é isso mesmo: toda coluna tem um padrão, e quando você não escreve nenhum, o padrão é NULL.
1. O primeiro DEFAULT
A tabela pedidos da Loja Aurora tem frete REAL NOT NULL DEFAULT 0. Um pedido novo, sem falar do frete:
INSERT INTO pedidos (cliente_id, funcionario_id, data) VALUES (27, 3, '2026-10-18'); SELECT * FROM pedidos WHERE id = 91;
O pedido 91 entrou com frete 0.0 (o padrão 0, guardado como número com decimais porque a coluna é REAL) e entregue_em NULL (a coluna não tem DEFAULT, então o padrão dela é NULL). E o id 91 veio de onde? Da chave primária, que se numera sozinha: assunto da aula PRIMARY KEY.
Agora uma tabela nova, com vários padrões:
CREATE TABLE avaliacoes (
id INTEGER,
produto_id INTEGER NOT NULL,
nota INTEGER NOT NULL DEFAULT 5,
comentario TEXT DEFAULT 'Sem comentário',
aprovada INTEGER NOT NULL DEFAULT 0
);
INSERT INTO avaliacoes (id, produto_id) VALUES (1, 3);
SELECT * FROM avaliacoes;
- DEFAULT 5
- Um número: se o
INSERTnão disser a nota, ela vale 5. - DEFAULT 'Sem comentário'
- Um texto, entre aspas simples, como todo texto em SQL.
- NOT NULL DEFAULT 0
- As duas regras juntas: a coluna é obrigatória, mas nunca vai faltar, porque tem um padrão. É o par mais comum (aula NOT NULL).
- (id, produto_id)
- O
INSERTsó falou de duas colunas; as outras três receberam os seus padrões.
A forma geral é sempre a mesma: o DEFAULT vem depois do tipo, junto das outras restrições, e a ordem entre elas não importa (NOT NULL DEFAULT 0 e DEFAULT 0 NOT NULL dão no mesmo).
nome_da_coluna TIPO [NOT NULL] DEFAULT valor
E quando o INSERT informa a coluna? Aí vale o que ele mandou, e o padrão é ignorado:
CREATE TABLE avaliacoes (
id INTEGER,
produto_id INTEGER NOT NULL,
nota INTEGER NOT NULL DEFAULT 5,
comentario TEXT DEFAULT 'Sem comentário'
);
INSERT INTO avaliacoes (id, produto_id, nota, comentario)
VALUES (1, 3, 2, 'A ponta quebra fácil');
SELECT * FROM avaliacoes;
Experimente: toda entrega nova da loja começa com a situação pendente. Rode e veja: como o INSERT não fala da coluna situacao, ela ficou NULL. Dê à coluna o valor padrão 'pendente', sem mexer no INSERT.
CREATE TABLE entregas (
id INTEGER,
pedido_id INTEGER NOT NULL,
situacao TEXT
);
INSERT INTO entregas (id, pedido_id) VALUES (1, 86);
SELECT * FROM entregas;
CREATE TABLE entregas (
id INTEGER,
pedido_id INTEGER NOT NULL,
situacao TEXT DEFAULT 'pendente'
);
INSERT INTO entregas (id, pedido_id) VALUES (1, 86);
SELECT * FROM entregas;
2. A data de hoje: CURRENT_DATE
"Quando esta avaliação foi feita?" É o caso clássico de valor padrão: a data do momento em que a linha entrou. O SQLite tem três palavras especiais para isso:
| Palavra | Formato | Exemplo |
|---|---|---|
CURRENT_DATE | AAAA-MM-DD | 2026-10-18 |
CURRENT_TIME | HH:MM:SS | 13:53:14 |
CURRENT_TIMESTAMP | AAAA-MM-DD HH:MM:SS | 2026-10-18 13:53:14 |
CREATE TABLE avaliacoes (
id INTEGER,
produto_id INTEGER NOT NULL,
criada_em TEXT NOT NULL DEFAULT CURRENT_DATE
);
INSERT INTO avaliacoes (id, produto_id) VALUES (1, 3);
SELECT * FROM avaliacoes;
O quadro mostra a data de hoje, o dia em que você está lendo esta página: o SQLite calculou na hora em que o INSERT rodou, no seu navegador. Rode amanhã e verá outra data.
A documentação do SQLite diz: esses valores são a data e a hora atuais em UTC (o "horário universal", o de Londres no inverno). O Brasil (o horário de Brasília) está 3 horas atrás. A Ana viu isso no terminal: a avaliação gravou 13:53, mas no relógio do notebook dela eram 10:53. Para mostrar no horário local, converta na consulta com datetime(…, 'localtime'):
$ 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, criada_em TEXT DEFAULT CURRENT_TIMESTAMP); sqlite> INSERT INTO avaliacoes (id, produto_id) VALUES (1, 3); sqlite> SELECT * FROM avaliacoes; 1|3|2026-10-18 13:53:14 « guardado em UTC sqlite> SELECT datetime(criada_em, 'localtime') FROM avaliacoes; 2026-10-18 10:53:14 « o mesmo instante, no fuso do notebook sqlite> .quit
Perto da meia-noite isso pesa até no CURRENT_DATE: às 22h no Brasil, em UTC já é o dia seguinte. Guardar em UTC é uma boa prática (todos os registros ficam na mesma régua); só lembre de converter na hora de mostrar. Mais em Datas e Horas.
3. Padrões calculados: a expressão entre parênteses
E se o padrão precisa de uma conta? Um cupom de desconto, por exemplo, que vale por 30 dias a partir de hoje. A função date('now', '+30 days') (aula Funções de Data) calcula essa data. Para usar uma expressão como padrão, ela vai entre parênteses:
CREATE TABLE cupons (
codigo TEXT NOT NULL,
desconto REAL NOT NULL DEFAULT 10,
validade TEXT NOT NULL DEFAULT (date('now', '+30 days'))
);
INSERT INTO cupons (codigo) VALUES ('AURORA10');
SELECT codigo, desconto, validade > date('now') AS ainda_vale FROM cupons;
- DEFAULT ( … )
- Os parênteses dizem "isto é uma expressão: calcule". O SQLite calcula uma vez para cada linha inserida.
- date('now', '+30 days')
- A data de hoje mais 30 dias, no formato
AAAA-MM-DD. - validade > date('now')
- Só para conferir: a validade é depois de hoje, então dá 1 ("verdadeiro"). (Mostrar a data em si daria um valor diferente a cada dia.)
Sem os parênteses, o SQLite não entende (veja em Quando dá errado). Os valores "simples" (um número, um texto entre aspas, NULL, TRUE, CURRENT_DATE…) não precisam de parênteses.
O padrão não pode olhar outras colunas
A Ana tentou um preço promocional que fosse, por padrão, 90% do preço normal:
CREATE TABLE ofertas (
produto_id INTEGER NOT NULL,
preco REAL NOT NULL,
preco_promo REAL DEFAULT (preco * 0.9)
);
"O valor padrão da coluna preco_promo não é constante." A expressão de um DEFAULT pode usar funções e contas, mas não pode citar colunas (nem a da própria linha), nem fazer consultas a outras tabelas. O padrão é decidido antes de a linha existir. Para "90% do preço", calcule no INSERT ou na consulta (SELECT preco * 0.9 …).
4. DEFAULT VALUES: uma linha só de padrões
Se todas as colunas têm um padrão que serve, existe um atalho: INSERT INTO tabela DEFAULT VALUES, sem lista de colunas e sem VALUES (…).
CREATE TABLE contadores (
visitas INTEGER NOT NULL DEFAULT 0,
situacao TEXT NOT NULL DEFAULT 'aberto'
);
INSERT INTO contadores DEFAULT VALUES;
INSERT INTO contadores DEFAULT VALUES;
SELECT * FROM contadores;
Duas linhas iguais, só com os padrões. Uma coluna sem DEFAULT receberia NULL (e, se fosse NOT NULL, o comando daria erro). Na prática, é um comando raro; ele aparece mais em tabelas cujo id se numera sozinho.
5. DEFAULT numa tabela que já existe
A Loja Aurora vai começar a marcar os produtos em promoção. A coluna nova entra com ALTER TABLE (aula ALTER TABLE), e o DEFAULT preenche os 45 produtos que já existem:
ALTER TABLE produtos ADD COLUMN em_promocao INTEGER NOT NULL DEFAULT 0; SELECT id, nome, em_promocao FROM produtos LIMIT 3;
Todos ganharam 0. Sem o DEFAULT, essa coluna NOT NULL não poderia nem ser criada (o erro está na aula NOT NULL). Mas há um limite: no ALTER TABLE, o SQLite só aceita padrões constantes. A data de hoje não serve:
ALTER TABLE produtos ADD COLUMN cadastrado_em TEXT DEFAULT CURRENT_TIMESTAMP;
"Não é possível acrescentar uma coluna com padrão não constante." A saída é acrescentar a coluna com um padrão fixo (ou sem padrão) e preencher depois com um UPDATE.
Formas diferentes de usar o padrão
| Forma | Exemplo | Quando usar |
|---|---|---|
Deixar a coluna fora do INSERT | INSERT INTO avaliacoes (id, produto_id) VALUES (1, 3); | O jeito normal: o padrão entra sozinho |
DEFAULT VALUES | INSERT INTO contadores DEFAULT VALUES; | Todas as colunas com o padrão |
| Escrever o valor | INSERT INTO avaliacoes (id, produto_id, nota) VALUES (1, 3, 5); | Quando você quer deixar claro o valor, mesmo que seja igual ao padrão |
DEFAULT dentro do VALUES | VALUES (1, 3, DEFAULT) | Não funciona no SQLite (dá erro de sintaxe); funciona no PostgreSQL, no MySQL e no SQL Server |
| Valor padrão | Exemplo | Precisa de parênteses? |
|---|---|---|
| Número | DEFAULT 0, DEFAULT -1, DEFAULT 4.5 | Não |
| Texto | DEFAULT 'pendente' | Não |
| Verdadeiro/falso | DEFAULT TRUE (vira 1) | Não |
NULL | DEFAULT NULL (o mesmo que não escrever) | Não |
| Data e hora atuais (UTC) | DEFAULT CURRENT_DATE, DEFAULT CURRENT_TIMESTAMP | Não |
| Expressão | DEFAULT (date('now', '+30 days')) | Sim |
Para ver o padrão de cada coluna, o PRAGMA table_info mostra na coluna dflt_value (de default value), exatamente como foi escrito:
SELECT name, "notnull", dflt_value FROM pragma_table_info('produtos');
Quando dá errado
NULL esperando o padrão
O padrão só entra quando a coluna fica de fora. Um NULL escrito no INSERT é um valor como outro qualquer, e ele ganha do padrão:
CREATE TABLE avaliacoes (
id INTEGER,
produto_id INTEGER NOT NULL,
comentario TEXT DEFAULT 'Sem comentário'
);
INSERT INTO avaliacoes (id, produto_id, comentario) VALUES (1, 3, NULL);
SELECT * FROM avaliacoes;
O comentário ficou NULL, não "Sem comentário". Se a coluna for NOT NULL, é pior: erro. Na tabela pedidos, o frete é NOT NULL DEFAULT 0:
INSERT INTO pedidos (cliente_id, funcionario_id, data, frete) VALUES (27, 3, '2026-10-18', NULL);
Como consertar: para usar o padrão, tire a coluna da lista do INSERT. Isso costuma acontecer em programas que montam o INSERT sempre com todas as colunas e mandam NULL nas que o usuário não preencheu.
INSERT sem lista de colunas
CREATE TABLE entregas (id INTEGER, situacao TEXT DEFAULT 'pendente'); INSERT INTO entregas VALUES (1);
O que diz: table entregas has 2 columns but 1 values were supplied. Sem a lista de colunas, o INSERT precisa de um valor para cada coluna, e o padrão não "completa" o que faltou. Como consertar: INSERT INTO entregas (id) VALUES (1);. Escrever a lista de colunas é sempre uma boa prática.
CREATE TABLE cupons (
codigo TEXT NOT NULL,
validade TEXT DEFAULT date('now', '+30 days')
);
O que diz: near "(": syntax error. Depois do DEFAULT, o SQLite esperava um valor simples, leu date e tropeçou no parêntese. Como consertar: ponha a expressão inteira entre parênteses: DEFAULT (date('now', '+30 days')).
DEFAULT dentro do VALUES
CREATE TABLE entregas (id INTEGER, situacao TEXT DEFAULT 'pendente'); INSERT INTO entregas (id, situacao) VALUES (1, DEFAULT);
O que diz: near "DEFAULT": syntax error. Quem vem do PostgreSQL ou do MySQL estranha, porque lá isso funciona. Como consertar: no SQLite, tire a coluna da lista: INSERT INTO entregas (id) VALUES (1);.
CREATE TABLE notas (id INTEGER, nota INTEGER DEFAULT 'cinco'); INSERT INTO notas (id) VALUES (1); SELECT nota, typeof(nota) FROM notas;
O que acontece: o CREATE TABLE não confere se o padrão combina com o tipo, e a tabela normal guarda o texto 'cinco' numa coluna INTEGER (aula Os Tipos no SQLite). Numa tabela STRICT, o erro aparece no primeiro INSERT: cannot store TEXT value in INTEGER column notas.nota. Como evitar: confira que o padrão é do mesmo tipo da coluna.
DEFAULT é do SQL padrão e se escreve igual no MySQL, no PostgreSQL e no SQL Server: frete DECIMAL(10,2) NOT NULL DEFAULT 0. Duas diferenças úteis:
- Os três aceitam a palavra
DEFAULTno lugar de um valor, dentro doVALUES, para pedir o padrão de uma coluna (trecho ilustrativo, não roda no SQLite):
INSERT INTO entregas (id, situacao) VALUES (1, DEFAULT);
INSERT INTO tabela DEFAULT VALUESexiste também no PostgreSQL e no SQL Server. No MySQL, a forma documentada éINSERT INTO tabela () VALUES ();.
Referência rápida
| Escrita | O que faz |
|---|---|
coluna TIPO DEFAULT valor | Valor usado quando o INSERT deixa a coluna de fora |
coluna TIPO NOT NULL DEFAULT valor | Obrigatória, com padrão |
DEFAULT CURRENT_DATE / CURRENT_TIME / CURRENT_TIMESTAMP | Data, hora ou data e hora do momento do INSERT, em UTC |
DEFAULT (expressão) | Padrão calculado a cada linha; sem citar colunas |
INSERT INTO t DEFAULT VALUES; | Uma linha só com os padrões |
SELECT name, dflt_value FROM pragma_table_info('t'); | Mostra o padrão de cada coluna |
| Mensagem do SQLite | Quer dizer |
|---|---|
near "(": syntax error | Uma expressão no DEFAULT sem parênteses |
default value of column [x] is not constant | O padrão cita uma coluna (ou faz uma consulta) |
Cannot add a column with non-constant default | ALTER TABLE … ADD COLUMN com CURRENT_TIMESTAMP ou expressão |
near "DEFAULT": syntax error | DEFAULT dentro do VALUES, que o SQLite não aceita |
NOT NULL constraint failed: t.c | Mandou NULL numa coluna NOT NULL, mesmo que ela tenha padrão |
Exercícios
1. País padrão
Complete para que o país dos fornecedores novos seja Brasil quando ninguém informar:
2. A data de hoje
Complete com a palavra que dá a data de hoje (sem a hora):
3. A coluna é comentario TEXT DEFAULT 'Sem comentário'. O INSERT manda NULL nela. O que fica guardado?
4. Qual destes DEFAULT dá erro no SQLite?
5. Em que fuso horário o CURRENT_TIMESTAMP do SQLite grava a hora?
6. Por que preco_promo REAL DEFAULT (preco * 0.9) dá erro?
Missão final: avaliações com padrões
Missão: toda avaliação nova começa não aprovada (a coluna aprovada vale 0) e guarda a data em que foi feita (a coluna criada_em, com a data de hoje). As duas colunas são obrigatórias. Complete o CREATE TABLE com NOT NULL e o DEFAULT certo em cada uma; os INSERT não falam delas, e têm de continuar funcionando.
CREATE TABLE avaliacoes (
id INTEGER,
produto_id INTEGER NOT NULL,
nota INTEGER NOT NULL,
aprovada INTEGER,
criada_em TEXT
);
INSERT INTO avaliacoes (id, produto_id, nota) VALUES (1, 3, 5);
INSERT INTO avaliacoes (id, produto_id, nota) VALUES (2, 10, 4);
PRAGMA table_info(avaliacoes);
CREATE TABLE avaliacoes (
id INTEGER,
produto_id INTEGER NOT NULL,
nota INTEGER NOT NULL,
aprovada INTEGER NOT NULL DEFAULT 0,
criada_em TEXT NOT NULL DEFAULT CURRENT_DATE
);
INSERT INTO avaliacoes (id, produto_id, nota) VALUES (1, 3, 5);
INSERT INTO avaliacoes (id, produto_id, nota) VALUES (2, 10, 4);
PRAGMA table_info(avaliacoes);
Depois de cumprir, troque o PRAGMA por SELECT * FROM avaliacoes; para ver as duas avaliações com o 0 e a data de hoje.
Resumo
DEFAULT valordá à coluna um valor padrão, usado quando oINSERTa deixa de fora. SemDEFAULT, o padrão éNULL.- O padrão pode ser um número, um texto entre aspas simples,
NULL,TRUE/FALSE,CURRENT_DATE,CURRENT_TIMEouCURRENT_TIMESTAMP(em UTC), ou uma expressão entre parênteses que não cite colunas. NULLescrito noINSERTnão aciona o padrão: ficaNULL(ou dá erro, se a coluna forNOT NULL).INSERT INTO t DEFAULT VALUES;cria uma linha só com padrões. O SQLite não aceitaDEFAULTdentro doVALUES.- No
ALTER TABLE … ADD COLUMN, o padrão preenche as linhas antigas, mas tem de ser constante.