Todos os Tipos SQL: Para que servem, Onde usar e O que muda entre A, B ou C
Consulte todos os tipos de campos do banco de dados organizados por categoria funcional. Entenda exatamente para que serve cada tipo, onde aplicar no seu projeto e o que muda na prática se você escolher o tipo A, B ou C na hora de desenhar no DrawDB e programar em PHP.
1. Textos e Caracteres (Strings Curtas e Longas)
Para nomes, documentos, e-mails, senhas, descrições, artigos HTML e observações.
⚖️ O que muda se eu usar (A) CHAR, (B) VARCHAR ou (C) TEXT?
Comparativo de Impacto Real (A vs B vs C)Opção A: Usar CHAR(n)
Opção B: Usar VARCHAR(n)
Opção C: Usar TEXT (TINY / TEXT / MEDIUM / LONG)
📌 Para que serve este Tipo SQL:
Armazenar códigos e siglas que têm SEMPRE a mesma quantidade exata de caracteres em todos os cadastros.
📍 Onde posso usar:
- • Sigla de Estado / UF: CHAR(2) -> "SP", "RJ", "MG"
- • CEP sem traço: CHAR(8) -> "01310100"
- • CPF sem pontos: CHAR(11) -> "01234567890"
- • CNPJ sem pontos: CHAR(14) -> "12345678000199"
- • UUID padrão: CHAR(36) | Hash SHA-256: CHAR(64)
⚖️ O que muda se eu escolher este?
Se escolher CHAR em vez de VARCHAR para CPF/UF, você economiza 1 byte de controle por linha e evita fragmentação quando o registro é atualizado.
📌 Para que serve este Tipo SQL:
Armazenar textos curtos ou médios cujo comprimento varia de um registro para outro, mas possui um teto máximo conhecido.
📍 Onde posso usar:
- • Nome de pessoa ou produto: VARCHAR(120)
- • E-mail de login (com UNIQUE): VARCHAR(150)
- • Senha com password_hash() do PHP: VARCHAR(255)
- • Telefone / WhatsApp: VARCHAR(20)
- • Caminho de imagem / URL: VARCHAR(255)
⚖️ O que muda se eu escolher este?
Se escolher VARCHAR(150) em vez de TEXT, você consegue colocar índice UNIQUE (essencial para e-mail e slug), definir DEFAULT e fazer buscas rápidas por igualdade (`WHERE email = :email`).
📌 Para que serve este Tipo SQL:
Texto curto armazenado fora da linha principal (raramente necessário hoje em dia).
📍 Onde posso usar:
- • Notas rápidas ou resumos curtos quando a tabela já atingiu o limite de 65.535 bytes das colunas VARCHAR.
⚖️ O que muda se eu escolher este?
Na prática, quase sempre é melhor usar VARCHAR(255) do que TINYTEXT, pois VARCHAR(255) aceita valor DEFAULT e índices completos nativamente.
📌 Para que serve este Tipo SQL:
Armazenar textos longos de vários parágrafos sem poluir a linha principal da tabela.
📍 Onde posso usar:
- • Descrição detalhada de um produto no e-commerce
- • Comentários de clientes, avaliações ou mensagens de suporte
- • Biografia de usuário, prontuário médico ou observações de pedido
⚖️ O que muda se eu escolher este?
Se o texto passar de 64 KB (ex: um artigo imenso com HTML pesado), o MySQL vai cortar ou recusar o INSERT! Se puder passar de 64 KB, mude para MEDIUMTEXT.
📌 Para que serve este Tipo SQL:
Armazenar conteúdos editoriais extensos, páginas completas de blog em HTML/Markdown ou templates de documentos.
📍 Onde posso usar:
- • Corpo completo de notícias, artigos de blog e apostilas em HTML/Markdown
- • Termos de uso, contratos jurídicos completos
- • Logs detalhados de erro ou respostas de API externas em texto
⚖️ O que muda se eu escolher este?
Muda o teto de 64 KB (do TEXT comum) para 16 Megabytes, custando apenas 1 byte a mais no cabeçalho do campo (3 bytes em vez de 2). É o tipo ideal para CMS e Blogs!
📌 Para que serve este Tipo SQL:
Capacidade extrema de texto para livros inteiros, transcrições massivas ou dumps de dados.
📍 Onde posso usar:
- • Acervos literários completos, código-fonte de projetos inteiros ou arquivos XML/CSV gigantes guardados para processamento.
⚖️ O que muda se eu escolher este?
Suporta até 4 GB por célula, mas cuidado no PHP: ler uma coluna LONGTEXT de centenas de megabytes com fetch() comum pode estourar o `memory_limit` do PHP!
2. Números Inteiros (Contagens, Quantidades e Códigos)
Para números sem vírgula: idades, estrelas, estoque, visualizações, anos e IDs.
⚖️ O que muda se eu usar (A) TINYINT, (B) SMALLINT, (C) INT ou (D) BIGINT? E Signed vs UNSIGNED?
Comparativo de Impacto Real (A vs B vs C)Opção A: TINYINT (1 Byte) ou SMALLINT (2 Bytes)
Opção B: INT / INTEGER (4 Bytes)
Opção C: BIGINT (8 Bytes) + Diferença UNSIGNED
📌 Para que serve este Tipo SQL:
Guardar números inteiros muito pequenos cujo valor jamais passará de 255.
📍 Onde posso usar:
- • Idade de uma pessoa (0 a 150)
- • Nota de avaliação / estrelas (1 a 5 ou 0 a 10)
- • Dia da semana (1 a 7), mês do ano (1 a 12)
- • Número de parcelas no cartão (1 a 24)
⚖️ O que muda se eu escolher este?
Gasta apenas 1 byte (8x menor que um BIGINT). Se marcar UNSIGNED, impede valores negativos como idade -5.
📌 Para que serve este Tipo SQL:
Guardar números inteiros pequenos/médios que passam de 255 mas não passam de 65 mil.
📍 Onde posso usar:
- • Ano de publicação/fabricação (ex: 1500 a 2100)
- • Quantidade de páginas de um livro ou carga horária de curso
- • Quantidade de unidades de um item dentro de um pedido
- • Ordem de exibição de categorias/banners (1, 2, 3...)
⚖️ O que muda se eu escolher este?
Economiza metade do espaço de um INT comum (2 bytes vs 4 bytes) mantendo folga até 65.535.
📌 Para que serve este Tipo SQL:
Faixa intermediária exclusiva do MySQL para contadores de até 16,7 milhões.
📍 Onde posso usar:
- • IDs de tabelas de médio porte ou códigos municipais IBGE (7 dígitos) em projetos exclusivamente MySQL.
⚖️ O que muda se eu escolher este?
Se você migrar o banco para PostgreSQL no futuro, o Postgres não tem MEDIUMINT (terá que virar INTEGER de 4 bytes). Na dúvida, use INT.
📌 Para que serve este Tipo SQL:
O inteiro universal padrão de qualquer banco de dados relacional.
📍 Onde posso usar:
- • Saldo de estoque de produtos (`estoque_atual INT NOT NULL DEFAULT 0`)
- • Duração de vídeos ou músicas em segundos
- • Contador de visualizações, downloads ou curtidas
- • Chaves primárias e estrangeiras de tabelas de até centenas de milhões de linhas
⚖️ O que muda se eu escolher este?
É 100% compatível com todos os bancos (MySQL, PostgreSQL, SQLite, SQL Server) e tem velocidade máxima no processador.
📌 Para que serve este Tipo SQL:
Números inteiros gigantescos, chaves primárias de alto volume e valores monetários armazenados em centavos.
📍 Onde posso usar:
- • Chave primária (`id BIGINT UNSIGNED AUTO_INCREMENT`) de pedidos, logs, mensagens, notas fiscais
- • Contadores globais de redes sociais ou eventos de telemetria
- • Valores em centavos quando se usa o padrão Money Pattern
⚖️ O que muda se eu escolher este?
Garante que a tabela nunca vai travar por falta de IDs disponíveis, ao custo de usar 8 bytes por coluna em vez de 4.
3. Números com Vírgula: Decimais Exatos vs Ponto Flutuante
Para dinheiro, preços, salários, impostos, pesos em kg, medidas e sensores.
⚖️ O que muda se eu usar (A) DECIMAL, (B) FLOAT ou (C) DOUBLE?
Comparativo de Impacto Real (A vs B vs C)Opção A: Usar DECIMAL(M, D) / NUMERIC(M, D)
Opção B: Usar FLOAT (4 Bytes)
Opção C: Usar DOUBLE / REAL (8 Bytes)
📌 Para que serve este Tipo SQL:
Armazenar qualquer valor onde cada casa depois da vírgula precisa ser 100% exata. M = total de dígitos; D = casas após a vírgula.
📍 Onde posso usar:
- • Preços, salários, fretes, descontos: DECIMAL(10, 2) -> até 99.999.999,99
- • Saldos financeiros grandes: DECIMAL(14, 2)
- • Peso em quilos/gramas: DECIMAL(8, 3) -> ex: 1,250 kg
- • Cotações cambiais e criptomoedas: DECIMAL(18, 8)
⚖️ O que muda se eu escolher este?
Garante precisão contábil absoluta. Se tentar gravar 3 casas decimais em um DECIMAL(10,2), o banco arredonda para 2 casas automaticamente.
📌 Para que serve este Tipo SQL:
Medições físicas contínuas e aproximadas que ocupam pouco espaço.
📍 Onde posso usar:
- • Temperatura ambiente (°C), umidade do ar (%), nível de bateria, leitura de sensores IoT
⚖️ O que muda se eu escolher este?
Ocupa pouco espaço, mas perde precisão a partir do 7º dígito. Nunca faça `WHERE preco = 10.50` em coluna FLOAT.
📌 Para que serve este Tipo SQL:
Cálculos científicos, engenharia, pontuação de algoritmos de recomendação e estatística.
📍 Onde posso usar:
- • Scores de relevância de busca, pesos matemáticos, vetores científicos
⚖️ O que muda se eu escolher este?
Dobra a precisão do FLOAT (usando 8 bytes em vez de 4), evitando estouros em números muito grandes ou muito pequenos.
4. Datas, Horários e Auditoria de Tempo
Para datas de nascimento, vencimentos, horários de expediente, agendamentos e logs (created_at).
⚖️ O que muda se eu usar (A) DATE, (B) DATETIME, (C) TIMESTAMP ou (D) TIME?
Comparativo de Impacto Real (A vs B vs C)Opção A: Usar DATE (Só Ano-Mês-Dia)
Opção B: Usar DATETIME (Data + Hora Fixa Civil)
Opção C: Usar TIMESTAMP (Carimbo de Tempo Universal UTC)
📌 Para que serve este Tipo SQL:
Registrar datas civis sem horário.
📍 Onde posso usar:
- • Data de nascimento (`data_nascimento DATE`)
- • Data de vencimento de boleto/fatura (`data_vencimento DATE`)
- • Data de emissão contábil ou início de contrato
⚖️ O que muda se eu escolher este?
Ao contrário de salvar em VARCHAR("19/10/2026"), o tipo DATE permite ordenar do mais antigo para o mais novo (`ORDER BY data_vencimento ASC`) e somar dias (`DATE_ADD`).
📌 Para que serve este Tipo SQL:
Guardar apenas o horário do relógio (sem dia/mês/ano) ou um intervalo de duração.
📍 Onde posso usar:
- • Horário de abertura e fechamento de uma loja (`08:00:00` às `18:00:00`)
- • Horário fixo de início de uma aula ou turno de trabalho
⚖️ O que muda se eu escolher este?
Permite consultar facilmente "quais lojas estão abertas agora" comparando `CURTIME() BETWEEN abre_as AND fecha_as`.
📌 Para que serve este Tipo SQL:
Registrar data e hora completas sem conversão de fuso horário e sem limite de ano 2038.
📍 Onde posso usar:
- • Data e hora de agendamentos (`data_hora_consulta DATETIME`)
- • Início e fim de promoções, eventos ou validade de certificados longos
⚖️ O que muda se eu escolher este?
Guarda exatamente a data/hora enviada pelo PHP, independentemente do timezone configurado no servidor MySQL.
📌 Para que serve este Tipo SQL:
Carimbo de tempo automático de quando um registro foi criado, alterado ou excluído.
📍 Onde posso usar:
- • Auditoria automática: `criado_em TIMESTAMP DEFAULT CURRENT_TIMESTAMP`
- • Última alteração: `atualizado_em TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP`
- • Exclusão lógica (Soft Delete): `deletado_em TIMESTAMP NULL`
⚖️ O que muda se eu escolher este?
Converte para UTC internamente e é mais leve (4 bytes), mas no MySQL não aceita datas antes de 1970 nem depois de 2038.
📌 Para que serve este Tipo SQL:
Guardar exclusivamente um número de ano com 4 dígitos gastando apenas 1 byte.
📍 Onde posso usar:
- • Ano de exercício fiscal, ano letivo escolar ou ano de fabricação (entre 1901 e 2155).
⚖️ O que muda se eu escolher este?
Economiza 1 byte em relação ao SMALLINT, mas só existe no MySQL/MariaDB e só vai de 1901 a 2155. Se precisar de anos antigos (ex: 1850) ou usar PostgreSQL, use SMALLINT.
5. Booleanos, Listas de Opções (ENUM/SET) e Documentos JSON
Para flags de verdadeiro/falso, status de pedidos, níveis de acesso e configurações flexíveis.
⚖️ O que muda se eu usar (A) ENUM, (B) VARCHAR com Enum no PHP ou (C) Tabela Separada (FK)?
Comparativo de Impacto Real (A vs B vs C)Opção A: Usar ENUM no Banco
Opção B: Usar VARCHAR(30) + BackedEnum no PHP 8
Opção C: Criar uma Tabela Separada com Foreign Key
📌 Para que serve este Tipo SQL:
Guardar respostas de Sim/Não, Ativo/Inativo, Ligado/Desligado.
📍 Onde posso usar:
- • Cadastro ativo (`ativo BOOLEAN NOT NULL DEFAULT 1`)
- • Produto em destaque (`destaque BOOLEAN NOT NULL DEFAULT 0`)
- • Frete grátis (`frete_gratis BOOLEAN NOT NULL DEFAULT 0`)
⚖️ O que muda se eu escolher este?
Ocupa apenas 1 byte e torna os filtros no PHP super limpos. Dica: se além de saber SE foi feito você precisar saber QUANDO foi feito (ex: e-mail verificado), troque `email_verificado BOOLEAN` por `email_verificado_em TIMESTAMP NULL`!
📌 Para que serve este Tipo SQL:
Armazenar máscaras de bits puras (flags binárias compactadas).
📍 Onde posso usar:
- • Sistemas legados ou máscaras de permissões binárias (b'0101').
⚖️ O que muda se eu escolher este?
Se escolher `BIT(1)` em vez de `BOOLEAN`/`TINYINT(1)` no MySQL, o PDO em PHP pode retornar o valor como um caractere binário invisível (`"\x00"` ou `"\x01"`), causando bugs em `if ($row['ativo'])`! Por isso, prefira sempre `BOOLEAN` / `TINYINT(1)` no MySQL.
📌 Para que serve este Tipo SQL:
Permitir que a coluna receba exatamente UM valor dentre uma lista fechada.
📍 Onde posso usar:
- • Status de pedido: ENUM('pendente', 'pago', 'enviado', 'cancelado')
- • Tipo de pessoa: ENUM('PF', 'PJ')
- • Método de pagamento: ENUM('pix', 'cartao', 'boleto')
⚖️ O que muda se eu escolher este?
O banco valida automaticamente a opção enviada e economiza espaço gravando apenas o índice numérico internamente.
📌 Para que serve este Tipo SQL:
Permitir escolher ZERO, UM ou VÁRIOS valores ao mesmo tempo de uma lista pré-definida.
📍 Onde posso usar:
- • Dias da semana de um alarme ou características simples fixas.
⚖️ O que muda se eu escolher este?
Difícil de filtrar individualmente e só existe no MySQL. Na prática moderna, é muito melhor usar uma coluna `JSON` (ex: `["seg", "qua"]`) ou uma tabela relacional N:N!
📌 Para que serve este Tipo SQL:
Guardar arrays, objetos aninhados e atributos variáveis sem precisar criar dezenas de colunas vazias.
📍 Onde posso usar:
- • Ficha técnica variável de produtos (ex: especificações de celular vs roupa)
- • Preferências de interface do usuário, logs de auditoria (valores antigos vs novos)
- • Retorno bruto de gateways de pagamento (Webhooks)
⚖️ O que muda se eu escolher este?
Se escolher `JSON` em vez de `TEXT`, o banco impede salvar um JSON com erro de sintaxe e permite consultar campos internos direto no SQL (`WHERE atributos->>"$.voltagem" = "220v"`). Mas nunca use JSON para guardar chaves estrangeiras!
6. Binários, Arquivos (BLOBs) e Coordenadas de Mapa (Geo)
Para bytes criptográficos, endereços IP compactados, anexos e coordenadas GPS.
⚖️ O que muda se eu salvar fotos/PDFs em (A) VARCHAR (Caminho/URL) vs (B) BLOB (Dentro do Banco)?
Comparativo de Impacto Real (A vs B vs C)Opção A: Usar VARCHAR(255) com o Caminho/URL do Arquivo (RECOMENDADO)
Opção B: Usar BLOB / MEDIUMBLOB / LONGBLOB (Arquivo dentro do Banco)
Opção C: Usar BINARY(16) / VARBINARY(16)
📌 Para que serve este Tipo SQL:
Armazenar sequências curtas de bytes brutos (sem tabela de caracteres/acentos).
📍 Onde posso usar:
- • Endereços IPv4 e IPv6 compactados com `inet_pton()`: VARBINARY(16)
- • UUID compactado em bytes: BINARY(16)
- • Hash SHA-256 binário puro: BINARY(32)
⚖️ O que muda se eu escolher este?
Compara byte a byte (muito mais rápido que comparar texto com collation UTF-8) e economiza até 55% de espaço em hashes e UUIDs.
📌 Para que serve este Tipo SQL:
Armazenar arquivos binários ou dados criptografados diretamente no banco.
📍 Onde posso usar:
- • Certificados digitais fiscais (.pfx) criptografados, assinaturas biométricas compactas
⚖️ O que muda se eu escolher este?
Diferente do TEXT, o BLOB não possui charset/collation (guarda bytes puros). Evite usar para fotos públicas do site (prefira salvar no disco e guardar a URL em VARCHAR).
📌 Para que serve este Tipo SQL:
Guardar um ponto geográfico (Longitude e Latitude) para cálculos nativos de distância em mapas.
📍 Onde posso usar:
- • Localização de lojas, entregadores ou imóveis para buscar "todos num raio de 5 km"
⚖️ O que muda se eu escolher este?
Se usar 2 colunas `DECIMAL(10,8)` e `DECIMAL(11,8)`, é muito mais simples de ler e gravar no PHP. Se usar `POINT`, você ganha o poder de criar um `SPATIAL INDEX` e usar `ST_Distance_Sphere()` no SQL!
📌 Para que serve este Tipo SQL:
Desenhar áreas fechadas no mapa (bairros, zonas de taxa de entrega, fazendas).
📍 Onde posso usar:
- • Verificar se o ponto GPS da casa do cliente cai dentro da área de cobertura de entrega (`ST_Contains`).
⚖️ O que muda se eu escolher este?
Permite que o próprio banco de dados responda se uma coordenada está dentro ou fora de um polígono desenhado no mapa.