Tipos de Dados
Tipos de Dados
Como caixas de armazenamento vêm em diferentes tamanhos — compartimentos pequenos para brincos, médios para relógios, grandes para cachecóis — cada coluna em um banco de dados também precisa da "caixa" certa para armazenar dados. Escolha o tipo certo e seus dados ficam seguros e com espaço eficiente; escolha errado e você desperdiça armazenamento ou perde precisão.
1. Conceitos Fundamentais
| Conceito | Descrição |
|---|---|
| Tipos numéricos | Armazenam inteiros e decimais, incluindo INT, BIGINT, DECIMAL, FLOAT, etc. |
| Tipos de string | Armazenam dados de texto, incluindo CHAR, VARCHAR, TEXT |
| Tipos de data | Armazenam datas e horários, incluindo DATE, DATETIME, TIMESTAMP |
| Tipos booleanos | Armazenam valores verdadeiro/falso; SQLite usa INTEGER (0/1) |
| NULL | Representa "desconhecido" ou "ausente" — não é uma string vazia, não é zero |
| Princípio de seleção de tipo | Escolha o tipo mais apropriado baseado no intervalo de dados, requisitos de precisão e eficiência de armazenamento |
2. Sintaxe Básica
Tipos Numéricos
| Tipo | Descrição | Intervalo/Precisão | Ideal Para |
|---|---|---|---|
INTEGER / INT |
Inteiro | ±2,1 bilhões | IDs, quantidades, idades |
BIGINT |
Inteiro grande | ±9,2×10¹⁸ | IDs para dados massivos, tamanhos de arquivo |
DECIMAL(p,s) / NUMERIC(p,s) |
Decimal exato | p = total de dígitos, s = casas decimais | Dinheiro, preços (sem perda de precisão) |
FLOAT / REAL |
Ponto flutuante | ~7 dígitos significativos | Cálculos científicos, aproximações |
DOUBLE |
Ponto flutuante de dupla precisão | ~15 dígitos significativos | Cálculos aproximados de alta precisão |
-- DECIMAL para armazenamento preciso de dinheiro
CREATE TABLE accounts (
id INTEGER PRIMARY KEY,
balance DECIMAL(12, 2) -- Até 12 dígitos, 2 casas decimais
);
-- FLOAT para armazenamento aproximado
CREATE TABLE measurements (
id INTEGER PRIMARY KEY,
temperature REAL -- Valor aproximado, pode ter pequenos erros
);
0.1 + 0.2 pode ser igual a 0.30000000000000004, o que é um desastre em cenários financeiros.
Tipos de String
| Tipo | Descrição | Tamanho Máximo | Ideal Para |
|---|---|---|---|
CHAR(n) |
String de comprimento fixo | 255 bytes | Dados de comprimento fixo (ex: gênero M/F, códigos de status) |
VARCHAR(n) |
String de comprimento variável | 65535 bytes | Nomes, e-mails, títulos |
TEXT |
Texto longo | Ilimitado | Conteúdo de artigos, notas, descrições |
CREATE TABLE articles (
id INTEGER PRIMARY KEY,
title VARCHAR(200), -- Título, máximo 200 caracteres
status CHAR(1), -- Status: D=Rascunho, P=Publicado
content TEXT -- Corpo, comprimento ilimitado
);
Tipos de Data
| Tipo | Descrição | Formato | Ideal Para |
|---|---|---|---|
DATE |
Data | YYYY-MM-DD |
Aniversários, datas de contratação |
DATETIME |
Data e hora | YYYY-MM-DD HH:MM:SS |
Horários de criação, horários de compromisso |
TIMESTAMP |
Timestamp | Gerenciado automaticamente | Horários de modificação de registro, cenários com fusos horários |
CREATE TABLE events (
id INTEGER PRIMARY KEY,
event_name TEXT,
event_date DATE, -- Apenas se importa com a data
created_at DATETIME DEFAULT CURRENT_TIMESTAMP -- Registra automaticamente o horário de criação
);
TEXT (formato ISO 8601 como '2024-01-15') ou INTEGER (timestamp Unix). As funções de data internas do SQLite (como DATE(), DATETIME()) podem lidar corretamente com esses formatos.
Tipos Booleanos
| Tipo | Descrição | Método de Armazenamento |
|---|---|---|
BOOLEAN |
Verdadeiro/Falso | Armazenado como INTEGER no SQLite: 0=falso, 1=verdadeiro |
BIT |
Valor de bit | Usado no MySQL/SQL Server |
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT,
is_active BOOLEAN DEFAULT 1 -- 1=habilitado, 0=desabilitado
);
-- Inserir valores booleanos
INSERT INTO users (name, is_active) VALUES ('John', TRUE); -- Armazenado como 1
INSERT INTO users (name, is_active) VALUES ('Jane', FALSE); -- Armazenado como 0
-- Consultar usando valores booleanos
SELECT * FROM users WHERE is_active = 1;
TRUE equivale a 1 e FALSE equivale a 0. Mas para legibilidade do código, é recomendado usar TRUE/FALSE em vez de escrever números diretamente.
O Significado de NULL
NULL representa "desconhecido" ou "ausente" — não é uma string vazia '', não é o número 0 e certamente não é FALSE.
-- Qualquer operação envolvendo NULL resulta em NULL
SELECT NULL + 1; -- Resultado: NULL
SELECT NULL || 'hello'; -- Resultado: NULL
-- Para verificar NULL, deve-se usar IS / IS NOT
SELECT * FROM employees WHERE department_id IS NULL; -- ✅ Correto
SELECT * FROM employees WHERE department_id = NULL; -- ❌ Sempre retorna vazio
SELECT * FROM employees WHERE department_id IS NOT NULL; -- ✅ Correto
IS para verificar NULL, não =; ②Qualquer operação envolvendo NULL resulta em NULL.
Boas Práticas de Seleção de Tipo
| Cenário | Tipo Recomendado | Razão |
|---|---|---|
| ID de chave primária | INTEGER PRIMARY KEY AUTOINCREMENT |
Inteiros são mais rápidos que strings; auto-incremento é conveniente |
| Dinheiro/Preços | DECIMAL(10,2) |
Armazenamento preciso, sem erros de arredondamento |
| Nomes de usuário/Títulos | VARCHAR(100) |
Comprimento variável economiza espaço; limite de comprimento previne abuso |
| Corpo de artigo | TEXT |
Comprimento ilimitado, adequado para grandes textos |
| Datas | DATE / DATETIME |
Semântica clara, suporte interno a funções de data |
| Sinalizadores Sim/Não | BOOLEAN |
Semântica clara, armazenamento compacto |
| Status de enumeração | CHAR(1) ou INTEGER |
Mais flexível que o tipo ENUM |
3. Exemplos de Código
Exemplo: Criar uma Tabela de Produtos e Verificar Restrições de Tipo (Dificuldade ⭐)
Crie uma tabela de produtos para experimentar o comportamento de diferentes tipos de dados.
-- Criar tabela products_demo com tipos de colunas especificados
CREATE TABLE products_demo (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(100) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
stock INTEGER DEFAULT 0,
description TEXT,
is_active BOOLEAN DEFAULT 1,
created_at DATE
);
-- Inserir dados de vários tipos
INSERT INTO products_demo (name, price, stock, description, is_active, created_at)
VALUES ('Mechanical Keyboard', 299.50, 100, 'Teclado mecânico blue switch 87 teclas, ótimo para digitação', TRUE, '2024-01-15');
INSERT INTO products_demo (name, price, stock, description, is_active, created_at)
VALUES ('Wireless Mouse', 89.00, 200, NULL, TRUE, '2024-02-20');
-- Visualizar dados e comportamento dos tipos
SELECT name, price, stock, description, is_active, created_at
FROM products_demo;
Saída:
name price stock description is_active created_at
---------------- ------- ----- --------------------------------------------- --------- ----------
Mechanical Keyboard 299.50 100 Teclado mecânico blue switch 87 teclas... 1 2024-01-15
Wireless Mouse 89.00 200 (NULL) 1 2024-02-20
Exemplo: Verificar Propriedades Aritméticas do NULL (Dificuldade ⭐⭐)
Entenda o comportamento especial do NULL através de consultas reais.
-- Criar tabela de teste
CREATE TABLE null_test (
id INTEGER PRIMARY KEY,
value INTEGER
);
INSERT INTO null_test VALUES (1, 10);
INSERT INTO null_test VALUES (2, NULL);
INSERT INTO null_test VALUES (3, 20);
-- NULL em operações aritméticas
SELECT id, value, value + 100 AS add_result
FROM null_test;
Saída:
id value add_result
-- ----- ----------
1 10 110
2 (NULL) (NULL)
3 20 120
-- Verificando NULL: IS vs =
SELECT id, value,
CASE WHEN value IS NULL THEN 'É NULL' ELSE 'Não é NULL' END AS check_result
FROM null_test;
Saída:
id value check_result
-- ----- ------------
1 10 Não é NULL
2 (NULL) É NULL
3 20 Não é NULL
-- NULL e funções de agregação: COUNT exclui NULL, SUM/AVG ignoram NULL
SELECT COUNT(value) AS count_val, -- 2 (não conta NULL)
COUNT(*) AS count_all, -- 3 (conta todas as linhas)
SUM(value) AS sum_val, -- 30 (ignora NULL)
AVG(value) AS avg_val -- 15 (30/2, não 30/3)
FROM null_test;
Saída:
count_val count_all sum_val avg_val
--------- --------- ------- -------
2 3 30 15.0
4. Cenários Comuns de Aplicação
Cenário 1: Projetar uma Tabela de Registro de Usuários
Escolha tipos apropriados baseados nos requisitos de negócio:
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username VARCHAR(50) NOT NULL UNIQUE, -- Nome de usuário, único e não nulo
email VARCHAR(100) NOT NULL UNIQUE, -- E-mail
password_hash CHAR(64) NOT NULL, -- Hash SHA256, fixo em 64 caracteres
age INTEGER CHECK (age >= 0 AND age <= 150), -- Idade, verificação de intervalo razoável
balance DECIMAL(12, 2) DEFAULT 0.00, -- Saldo da conta, preciso ao centavo
bio TEXT, -- Bio, comprimento ilimitado
is_verified BOOLEAN DEFAULT 0, -- Se o e-mail foi verificado
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
Cenário 2: Lidando com NULL e Valores Padrão
Use a função COALESCE para fornecer valores padrão para NULL:
-- Consultar informações do funcionário, mostrar "Não atribuído" quando o departamento é NULL
SELECT e.name,
COALESCE(d.name, 'Não atribuído') AS department,
COALESCE(e.salary, 0) AS salary
FROM employees e
LEFT JOIN departments d ON e.department_id = d.id;
❓ Perguntas Frequentes
P: DECIMAL(10,2) e FLOAT podem armazenar decimais. Qual a diferença? R: DECIMAL armazena valores exatos, adequado para dinheiro e outros cenários onde a precisão é crítica. FLOAT armazena valores aproximados, com computação mais rápida mas pequenos erros. Regra simples: Dinheiro usa DECIMAL, cálculos científicos usam FLOAT.
P: Como escolher entre CHAR e VARCHAR? R: Se o comprimento dos dados é fixo (ex: gênero M/F, hash MD5), CHAR é mais eficiente. Se o comprimento varia (ex: nomes, títulos), VARCHAR economiza mais espaço. Na prática, VARCHAR é usado mais frequentemente.
P: Qual a diferença entre NULL e uma string vazia ''? R: NULL significa "desconhecido/sem valor", enquanto uma string vazia significa "o valor é conhecido e está vazio". Por exemplo, uma coluna "nome do meio": um estrangeiro pode não ter nome do meio (NULL), enquanto um brasileiro pode ter mas é uma string vazia (''). Em funções de agregação, COUNT(coluna) não conta NULL mas conta strings vazias.
P: Como o sistema de tipos do SQLite difere de outros bancos de dados? R: SQLite usa um sistema de tipos dinâmico — declarações de tipo de coluna são mais como "sugestões" do que restrições estritas. Você pode inserir uma string em uma coluna INTEGER (embora não recomendado). MySQL, PostgreSQL e outros usam sistemas de tipos estritos onde incompatibilidades de tipo causam erros. Para portabilidade do código, use tipos corretamente.
📖 Resumo
- Tipos numéricos: Use INT/BIGINT para inteiros, DECIMAL para decimais exatos (obrigatório para dinheiro), FLOAT para valores aproximados
- Tipos de string: Use CHAR para comprimento fixo, VARCHAR para comprimento variável, TEXT para grandes textos
- Tipos de data: DATE armazena datas, DATETIME armazena datas com hora, TIMESTAMP gerencia automaticamente
- Tipos booleanos: BOOLEAN armazena TRUE/FALSE; no SQLite é na verdade INTEGER 0/1
- NULL significa "desconhecido"; verifique com
IS NULLnão= NULL; operações envolvendo NULL ainda resultam em NULL - Princípio de seleção de tipo: Considere intervalo de dados, requisitos de precisão e eficiência de armazenamento; sempre use DECIMAL para dinheiro
📝 Exercícios
Exercício 1 (⭐)
Projete uma tabela de "empréstimo de biblioteca" com os seguintes campos, escolhendo tipos de dados apropriados:
- ID do empréstimo (chave primária)
- Título do livro (máximo 200 caracteres)
- ISBN (fixo em 13 caracteres)
- Nome do mutuário
- Data do empréstimo
- Data de devolução
- Se foi devolvido
- Notas (anulável)
Exercício 2 (⭐⭐)
Crie a tabela do Exercício 1, insira 5 registros e depois escreva consultas:
- Consulte todos os registros de empréstimo não devolvidos
- Consulte registros onde as notas são NULL
- Conte todos os registros não devolvidos (cuidado com o tratamento de NULL)
Próxima Lição
👉 06-practice-basics - Prática: Consultas Básicas Abrangentes



