Ir para o conteúdo principal

Tipos de dados SQL: Referência e boas práticas

Tipos de dados SQL: tipos numéricos, de caracteres, data/hora e binários. Domine a otimização de armazenamento, o desempenho de consultas, as melhores práticas de integridade de dados e as diferenças entre provedores.

por Equipe da Databricks

  • Os tipos de dados SQL garantem a integridade dos dados validando os valores no momento da inserção, evitando a corrupção de dados em cargas de trabalho de analytics, BI e ML.
  • A escolha de tipos de dados com tamanho adequado melhora o desempenho das consultas ao maximizar a utilização do cache da CPU e reduzir os custos de transferência de rede em sistemas distribuídos.
  • As implementações de tipos de dados variam entre MySQL, PostgreSQL, SQL Server e Oracle; o tratamento específico de cada provedor para precisão e comportamento de datetime é essencial para a portabilidade do esquema.

Um tipo de dados SQL é uma especificação fundamental que define quais valores uma coluna pode conter e quanto espaço de armazenamento esses valores exigem em uma tabela de banco de dados. Compreender os tipos de dados SQL é essencial para quem cria pipelines de dados, escreve consultas ou projeta esquemas de banco de dados, pois esses tipos controlam diretamente a integridade dos dados, a eficiência do armazenamento e o desempenho das consultas. Ao definir uma coluna em uma tabela de banco de dados, você não está apenas especificando um nome — está estabelecendo um contrato sobre que tipo de informação residirá nessa coluna e como o banco de dados deve tratá-la.

A importância de escolher o tipo de dados correto não pode ser subestimada. Os tipos de dados SQL impõem regras lógicas sobre quais valores podem ser armazenados, evitando a inserção de dados inválidos em primeiro lugar. Eles também afetam drasticamente a rapidez com que suas consultas são executadas e quanto espaço em disco suas tabelas consomem. Um tipo de dados mal escolhido pode desacelerar as consultas, desperdiçar armazenamento e criar bugs sutis em seus pipelines de dados. Por outro lado, a seleção de tipos apropriados pode melhorar a escalabilidade a longo prazo e aumentar drasticamente o desempenho do banco de dados em cargas de trabalho de análise, aplicativos em tempo real e pipelines de features de machine learning.

Os tipos de dados SQL são categorizados amplamente em quatro grupos principais: tipos de dados numéricos para cálculos matemáticos, tipos de dados de caracteres e strings para texto, tipos de dados de data e hora para registrar quando os eventos ocorrem e tipos de dados especializados para dados binários e outros formatos. Diferentes sistemas de banco de dados — MySQL, PostgreSQL, SQL Server e Oracle — implementam cada uma dessas categorias com pequenas variações de nomenclatura, precisão e requisitos de armazenamento. Este guia fornece uma referência prática para compreender os tipos de dados SQL em sistemas de banco de dados comuns, além de práticas recomendadas para escolher o tipo certo para o seu caso de uso.

Entendendo o que um tipo de dados impõe

Um tipo de dados é mais do que apenas um rótulo. Quando você declara que uma coluna é do tipo INTEGER ou VARCHAR, está dizendo ao seu sistema de gerenciamento de banco de dados exatamente que tipo de valores pertencem a essa coluna e como tratá-los durante as consultas e o armazenamento. O banco de dados usa essas informações para validar os dados no momento da inserção, evitando entradas que violem as restrições do tipo. Sistemas de banco de dados modernos, como aqueles baseados em transações ACID, garantem que essa validação ocorra de forma confiável, mesmo durante padrões de acesso concorrente.

Considere um exemplo simples: se você definir uma coluna como INTEGER, o banco de dados rejeitará qualquer tentativa de inserir textos como "hello" ou valores não inteiros como 3.14. Essa validação ocorre de forma automática, impondo a integridade dos dados ao recusar o armazenamento de formatos de dados incorretos. Sem essa imposição, as consultas e análises downstream encontrariam dados corrompidos ou inconsistentes, levando a resultados incorretos e perda de tempo com depuração.

Os tipos de dados também comunicam a intenção a outros desenvolvedores e engenheiros de dados que trabalham com seu esquema. Quando alguém vê que uma coluna está definida como DECIMAL em vez de FLOAT, entende imediatamente que essa coluna armazena valores monetários precisos que não toleram erros de arredondamento. Essa documentação implícita reduz mal-entendidos e torna os esquemas mais fáceis de manter ao longo do tempo.

Como os tipos de dados afetam o armazenamento e o desempenho das consultas

A escolha do tipo de dados tem consequências diretas sobre a quantidade de espaço em disco que suas tabelas consomem e a rapidez com que as consultas podem ser executadas. A eficiência do armazenamento afeta suas faturas de nuvem, tempos de backup e quantas linhas você pode colocar na memória para processamento. O desempenho da consulta depende em parte do tamanho do tipo de dados — tipos menores podem ser processados mais rapidamente porque mais linhas cabem no cache da CPU e menos dados precisam ser transferidos entre o armazenamento e o processamento. Para equipes que criam pipelines de ETL que processam milhões de linhas diariamente, essas otimizações se traduzem em melhorias mensuráveis de custo e latência.

Os tipos de dados de string variam significativamente em sua pegada de armazenamento. Uma coluna CHAR sempre reserva seu comprimento total declarado, preenchendo com espaços mesmo se você armazenar um valor curto. Uma coluna VARCHAR, por outro lado, usa apenas o espaço necessário para o valor realmente armazenado. Se a maioria dos nomes de seus clientes tiver menos de 30 caracteres, armazená-los como VARCHAR(50) economiza um espaço substancial em comparação com CHAR(50). Essa economia de espaço se acumula em milhões de linhas e pode reduzir a latência da consulta porque mais dados cabem na memória disponível.

Os tipos numéricos também influenciam o desempenho. Usar BIGINT quando INT seria suficiente desperdiça armazenamento e processamento. Por outro lado, usar SMALLINT para uma coluna que precisa armazenar valores acima de 32.000 causa erros de overflow. Compreender os requisitos de intervalo e precisão de seus dados permite que você escolha o menor tipo de dados que armazena seus valores com segurança, mantendo seu banco de dados rápido e enxuto.

Os índices, que aceleram drasticamente o desempenho das consultas, são mais rápidos quando definidos em tipos de dados apropriados. Um índice em uma coluna TINYINT é mais eficiente do que um índice em uma coluna TEXT. Ao escolher tipos numéricos de tamanho adequado e evitar índices em colunas de texto muito grandes, você multiplica os benefícios de desempenho da indexação em toda a sua carga de trabalho. Mecanismos de consulta distribuída como o Apache Spark se beneficiam especialmente de tipos de dados dimensionados corretamente, pois tipos menores reduzem a transferência de rede durante as operações de shuffle.

Escolhendo o tipo de dados certo

A regra de ouro para a seleção do tipo de dados é usar o menor tipo que armazene seus dados com segurança. Esse princípio, aplicado de forma consistente durante o design do esquema, traz dividendos em eficiência de armazenamento, velocidade de consulta e escalabilidade do sistema. Antes de selecionar um tipo, pergunte-se: Qual é o valor máximo que esta coluna pode conter? De quanta precisão eu preciso? Esse valor algum dia será NULL?

Para dados numéricos, examine a distribuição real dos seus dados. Se uma coluna contiver valores entre 0 e 100, TINYINT é perfeito. Se você estiver armazenando IDs de clientes que podem exceder 2 bilhões, INT é suficiente; use BIGINT apenas se você realmente precisar de armazenamento para valores acima de 2 bilhões. Fazer essa distinção em dezenas de colunas em seu esquema pode reduzir o tamanho total da tabela em 20% a 30%, melhorando diretamente o desempenho da consulta.

Ao trabalhar com strings, considere o trade-off entre armazenamento e flexibilidade. CHAR força você a escolher um comprimento máximo e sempre usa esse espaço. VARCHAR permite que você armazene dados de comprimento variável com eficiência, mas exige que você escolha um máximo que não cause truncamento. VARCHAR(50) para nomes alcança um equilíbrio — é grande o suficiente para praticamente todos os nomes, mas evita o armazenamento acidental de valores extremamente longos que possam ser problemas de qualidade de dados. Para blocos de texto muito grandes, como corpos de artigos ou mensagens de log, use tipos TEXT ou CLOB que não exigem especificação prévia de comprimento.

Valide suas escolhas com dados de amostra antes de implantar em produção. Insira dados reais em uma tabela de teste com o esquema proposto e observe o uso real de armazenamento. Execute as consultas pretendidas e meça o desempenho. Essa abordagem empírica revela se suas escolhas oferecem suporte à carga de trabalho que você realmente está executando. As plataformas de banco de dados normalmente oferecem ferramentas para analisar planos de execução de consulta e identificar operações lentas causadas por tipos de dados abaixo do ideal.

Tipos de dados numéricos

Os tipos de dados numéricos armazenam números e vêm em duas famílias principais: tipos inteiros para números inteiros e tipos decimais ou de ponto flutuante para números com componentes fracionários.

Os tipos inteiros representam números inteiros sem casas decimais. O tipo de dados INTEGER, também chamado de INT, é a escolha mais comum para valores inteiros e armazena um número de 4 bytes que pode representar valores de aproximadamente -2 bilhões a +2 bilhões. Quando você precisa de um intervalo menor — por exemplo, armazenar valores de idade que não excederão 127 —, o TINYINT usa apenas um byte e é perfeito. O SMALLINT ocupa dois bytes e lida com valores de até cerca de 32.000, útil para colunas como quantidades ou contagens que permanecem relativamente pequenas. O BIGINT, um inteiro de 8 bytes, acomoda números astronômicos e é necessário ao armazenar IDs gerados a partir de sistemas distribuídos ou timestamps medidos em milissegundos.

O tipo de dados DECIMAL, às vezes chamado de NUMERIC na documentação padrão do SQL, armazena números de precisão fixa adequados para cálculos financeiros e outros contextos em que erros de arredondamento são inaceitáveis. O DECIMAL armazena valores exatos sem a aproximação inerente à aritmética de ponto flutuante. Quando você define DECIMAL(10,2), está dizendo "Quero armazenar números com até 10 dígitos no total, onde exatamente 2 desses dígitos estão à direita do ponto decimal". Essa precisão significa que o DECIMAL(10,2) armazena com segurança valores como 99999999.99, mas rejeitará qualquer coisa com mais de duas casas decimais. Bancos e sistemas de contabilidade dependem do DECIMAL porque as regulamentações financeiras exigem cálculos exatos e auditáveis, sem erros de arredondamento.

O NUMERIC serve como o nome padrão do SQL para dados decimais de precisão fixa e se comporta de maneira idêntica ao DECIMAL na maioria dos sistemas de banco de dados. Alguns bancos de dados usam NUMERIC e DECIMAL de forma intercambiável, enquanto outros os documentam separadamente por motivos históricos. Verifique a documentação do seu banco de dados para confirmar o comportamento exato, mas trate-os como funcionalmente equivalentes na prática.

A criação de uma tabela com colunas numéricas ilustra esses tipos em contexto. Uma tabela de vendas típica pode ser parecida com esta:

Aqui, employee_id usa INT porque os IDs de funcionários geralmente estão na casa dos milhões. O age usa TINYINT porque a idade humana nunca passa de 127. O salary e o bonus_percentage usam DECIMAL para garantir cálculos precisos durante o processamento da folha de pagamento, onde até mesmo pequenos erros de arredondamento se acumulam em toda a organização. Plataformas de dados modernas como o Delta Lake impõem esses tipos de forma estrita, garantindo que dados com tipos incorretos não possam ser inseridos em tabelas de produção.

Entendendo números de ponto flutuante

Tipos de ponto flutuante armazenam valores numéricos aproximados com uma precisão específica. FLOAT e DOUBLE usam a representação binária IEEE 754, que troca a exatidão pela velocidade e alcance. Um FLOAT geralmente ocupa 4 bytes e armazena valores aproximados, enquanto o DOUBLE ocupa 8 bytes e oferece maior precisão.

A representação de ponto flutuante introduz artefatos de arredondamento porque muitos valores decimais não podem ser representados exatamente em binário. Por exemplo, 0,1 não pode ser representado exatamente em ponto flutuante binário, portanto, qualquer cálculo que envolva 0,1 pode apresentar uma pequena diferença. Esses pequenos erros se acumulam em longas cadeias de cálculos, gerando resultados visivelmente incorretos com o tempo. Por esse motivo, você nunca deve usar FLOAT ou DOUBLE para dados monetários ou outros valores em que a exatidão seja fundamental.

A escolha apropriada entre DECIMAL e FLOAT depende do seu caso de uso. Use DECIMAL para dados financeiros, medições científicas precisas ou cálculos em que a exatidão precise ser auditável. Use FLOAT para aproximações, computação científica onde pequenos erros são aceitáveis ou recursos de machine learning onde a leve imprecisão não afeta a qualidade do modelo. O desempenho das consultas melhora com o uso de tipos de dados de tamanho adequado, e as operações com FLOAT são mais rápidas do que as com DECIMAL porque a matemática de ponto flutuante é acelerada por hardware em todos os processadores modernos.

Compare estas duas abordagens para armazenar preços de produtos:

A segunda versão garante que preços como 19,99 sejam armazenados exatamente, sem sofrer erros de arredondamento durante os cálculos ou a exibição. A primeira versão pode representar 19,99 como 19,989999... internamente, causando discrepâncias sutis nos cálculos totais e nos preços exibidos aos clientes.

Tipos de dados de data e hora

Os tipos de data e hora armazenam informações temporais — o momento em que os eventos ocorreram ou quando os dados devem ser considerados relevantes. Esses tipos são essenciais para análises de séries temporais, registro de eventos (logging) e processos de negócios que acompanham quando as coisas acontecem.

O tipo DATE armazena apenas a parte da data — ano, mês e dia — no formato YYYY-MM-DD, sem nenhum componente de hora. Use DATE quando precisar registrar apenas o dia em que algo aconteceu, como a data de nascimento de um cliente ou a data de uma transação, sem se importar com a hora ou o minuto exato. O DATE ocupa o mínimo de armazenamento (geralmente 3 bytes) e simplifica as consultas que agrupam eventos por dia civil.

O tipo TIME armazena apenas a parte da hora — horas, minutos e segundos — sem uma data. O TIME é menos comum do que o DATE ou o TIMESTAMP, mas aparece em esquemas que registram horários recorrentes, como horário comercial ou horários de compromissos em um dia.

O tipo TIMESTAMP (chamado de DATETIME em alguns sistemas como MySQL e SQL Server) armazena informações de data e hora no formato YYYY-MM-DD HH:MM:SS. O TIMESTAMP captura o momento completo em que algo ocorreu, com precisão de segundos (ou ainda mais precisa, dependendo do seu banco de dados). A maioria dos sistemas orientados a eventos usa TIMESTAMP para registrar exatamente quando as entradas de log foram criadas, quando os pedidos foram feitos ou quando as leituras dos sensores chegaram. Muitos sistemas analíticos criados com designs de star schema usam chaves TIMESTAMP para análise temporal eficiente e rastreamento de fatos históricos.

Escolha DATE ou TIMESTAMP com base nos seus padrões de consulta. Se a sua lógica de negócios agrupa eventos por data civil e nunca precisa de precisão intradiária, o DATE é mais limpo e eficiente. Se você precisar calcular o tempo decorrido entre eventos, detectar tendências dentro de uma hora ou manter uma ordem cronológica precisa, o TIMESTAMP é necessário.

Exemplos de definições de colunas de data e hora:

Aqui, birthdate usa DATE porque você só se importa com a data de nascimento da pessoa, não com a hora em que ela nasceu. account_creation_date usa TIMESTAMP porque você precisa saber precisamente quando a conta foi criada, potencialmente para detectar fraud padrões ou calcular a idade da conta em dias. preferred_contact_time usa TIME porque você está armazenando um horário recorrente como "ligue para mim às 14h" sem uma data específica.

Considerações sobre fuso horário para dados de data e hora

Uma questão sutil, mas crítica, nos dados temporais é o tratamento do fuso horário. Quando você registra que um evento ocorreu em "2024-03-15 14:30:00", isso significa 14h30 em Nova York, Tóquio ou UTC? A resposta é importante porque o mesmo horário de relógio significa coisas diferentes em fusos horários diferentes.

A melhor prática é armazenar todos os timestamps em UTC (Tempo Universal Coordenado), uma referência de tempo independente de fuso horário. Quando seu aplicativo receber um evento de um usuário em qualquer fuso horário, converta-o para UTC antes de armazená-lo no banco de dados. Essa abordagem garante que todos os timestamps sejam comparáveis e que você possa responder sem ambiguidade a perguntas como "quais eventos ocorreram primeiro?" ou "quanto tempo se passou entre esses eventos?".

Alguns bancos de dados como o PostgreSQL suportam TIMESTAMPTZ (timestamp com fuso horário), que armazena tanto o timestamp quanto as informações do fuso horário associado. Quando você recupera dados, o banco de dados converte o timestamp UTC de volta para o fuso horário original, se necessário. Essa abordagem preserva o contexto original do fuso horário, garantindo a consistência interna.

O DATETIME do SQL Server e o DATETIME do MySQL não incluem informações de fuso horário, portanto, converta os horários para UTC antes de armazenar e converta de volta ao exibir para os usuários. As configurações de sessão afetam a forma como os timestamps são interpretados em alguns bancos de dados, por isso documente suas premissas claramente.

EBOOK

Principais conclusões sobre sistemas multiagentes, casos de uso de IA, avaliações e muito mais

Dados de caracteres e Unicode

Os tipos de dados de caracteres armazenam texto e vêm em variantes de comprimento fixo e variável, cada uma adequada para cenários diferentes.

O CHAR armazena strings de comprimento fixo e sempre usa todo o comprimento declarado, preenchendo com espaços se o valor real for menor. O CHAR(10) sempre ocupa exatamente 10 bytes por linha, mesmo se você inserir "hello" (5 caracteres). O CHAR se destaca quando quase todos os valores têm o mesmo comprimento, como códigos postais dos EUA (5 dígitos) ou códigos de países (2 letras). O armazenamento de comprimento fixo simplifica a indexação e torna as varreduras de tabela previsíveis em tamanho.

O VARCHAR armazena strings de comprimento variável e usa apenas o espaço necessário para os dados reais, além de uma pequena sobrecarga para registrar o comprimento. O VARCHAR(100) que armazena "hello" ocupa cerca de 7 bytes (5 para "hello" mais 2 para codificação de comprimento), economizando 93 bytes em comparação com o CHAR(100) no mesmo valor. O VARCHAR deve ser dimensionado pensando nos dados reais — escolha VARCHAR(50) para nomes apenas se tiver certeza de que os nomes não passarão de 50 caracteres. Se os nomes costumam ter 30 caracteres, mas ocasionalmente podem chegar a 50, o VARCHAR(50) é prudente.

O TEXT acomoda grandes blocos de texto não estruturado sem um comprimento máximo declarado. Use TEXT para artigos, comentários ou documentos que variam muito de tamanho. Alguns bancos de dados diferenciam entre TEXT e tipos mais especializados como CLOB (Character Large Object), mas a maioria dos sistemas modernos lida com TEXT de forma eficiente com compressão interna e streaming.

Para textos internacionais que contêm caracteres de vários idiomas, use tipos compatíveis com Unicode: variantes NVARCHAR ou UTF8, dependendo do seu banco de dados. O NVARCHAR (VARCHAR nacional) no SQL Server armazena texto codificado em UTF-16, suportando qualquer caractere Unicode. O PostgreSQL e o MySQL suportam conjuntos de caracteres UTF-8 diretamente no VARCHAR com as configurações de agrupamento (collation) apropriadas. Sempre defina explicitamente a codificação de caracteres ao criar tabelas para evitar comportamentos inesperados caso o padrão do banco de dados seja alterado.

Exemplos de definições de colunas de string:

Aqui, first_name e last_name usam VARCHAR porque os nomes geralmente são curtos, mas variáveis, economizando espaço em comparação com o CHAR. biography usa TEXT porque as biografias dos clientes podem ser desde uma única frase até um parágrafo inteiro. country_code usa CHAR(2) porque todos os códigos de países têm exatamente 2 letras, tornando o armazenamento de comprimento fixo adequado.

Tipos de dados binários e strings binárias

Os tipos de dados binários armazenam dados binários brutos — sequências de bytes — em vez de texto. Esses tipos são úteis para armazenar imagens, arquivos, hashes criptográficos e outros conteúdos não textuais.

O BLOB (Binary Large Object) armazena dados binários arbitrários sem um limite máximo de tamanho. Use BLOB para imagens, documentos PDF, vídeos ou qualquer conteúdo binário não estruturado que não caiba nos tipos padrão. O BLOB é adequado quando você precisa armazenar arquivos no seu banco de dados, embora muitos sistemas de produção prefiram armazenar arquivos grandes em sistemas de armazenamento de objetos como o Amazon S3 e manter apenas as referências dos arquivos no banco de dados.

O VARBINARY armazena dados binários de comprimento variável com um tamanho máximo explícito. O VARBINARY(256) armazena até 256 bytes de dados binários, ocupando apenas o espaço necessário para o conteúdo real. O VARBINARY funciona bem para dados binários de tamanho fixo, como assinaturas criptográficas, checksums ou UUIDs.

O BINARY armazena dados binários de comprimento fixo, preenchendo com bytes nulos se necessário. O BINARY(16) sempre ocupa exatamente 16 bytes, o que é útil para armazenar identificadores de tamanho fixo, como UUIDs de 128 bits. O BINARY deve ser dimensionado com cuidado, pois o desperdício de espaço devido a declarações excessivamente grandes prejudica o desempenho.

Na prática, armazenar arquivos grandes em armazenamento de objetos (object storage) em vez de bancos de dados costuma ser melhor. O armazenamento de objetos é mais barato, mais rápido para arquivos grandes e escala mais facilmente do que o armazenamento em banco de dados. Mantenha a referência do arquivo e os metadados no banco de dados, não o arquivo em si.

Exemplo de definições de colunas binárias:

Aqui, o content usa BLOB para armazenar os dados reais do documento. O checksum usa VARBINARY para armazenar um hash SHA-256 (32 bytes) que verifica se o documento não foi corrompido. O uuid usa BINARY(16) para armazenar um identificador UUID de tamanho fixo.

Considerações práticas para dados binários

Indexar colunas binárias é complicado porque os índices B-tree tradicionais pressupõem que os valores são ordenáveis e comparáveis. Você pode indexar colunas BINARY para correspondências exatas, mas não para consultas de intervalo. Evite indexar colunas BLOB, a menos que seu banco de dados tenha índices de bitmap ou hash especializados projetados para dados binários.

Para verificar a integridade dos dados em conteúdos binários, mantenha uma coluna de checksum separada que armazene um hash dos dados binários. Se suspeitar de corrupção, recalcule o hash e compare-o com o valor armazenado. Essa abordagem é muito mais rápida do que reexaminar todo o conteúdo binário.

Tipo de dados booleano e dados booleanos

Os tipos de dados booleanos armazenam valores verdadeiro/falso (true/false), essenciais para sinalizadores (flags), indicadores de status e decisões de sim/não. Os valores verdadeiro e falso simplificam a modelagem de dados e evitam estados inválidos como NULL ou strings ambíguas como "yes" ou "1".

Diferentes bancos de dados implementam booleanos de maneiras distintas. O PostgreSQL possui um tipo BOOLEAN nativo que aceita true/false, yes/no, on/off, 1/0 em vários formatos. O MySQL trata o BOOLEAN como um número inteiro pequeno, mapeando-o como um alias para TINYINT(1), onde 1 representa true e 0 representa false. O SQL Server usa BIT para dados do tipo booleano, armazenando 1 para true e 0 para false usando um único bit por valor (embora o armazenamento real varie).

Compreender as diferenças entre provedores é importante ao migrar esquemas entre bancos de dados. Um BOOLEAN do PostgreSQL não tem um equivalente direto no SQL Server — em vez disso, você usaria BIT. O código de aplicativo que pressupõe a entrada flexível de true/false do PostgreSQL (que aceita "yes", "on", "1") pode falhar com os requisitos estritos de 0/1 do SQL Server.

Exemplos de definições booleanas:

Todos os três são funcionalmente idênticos no armazenamento de valores true/false, mas os nomes dos tipos subjacentes diferem, e o comportamento de entrada/saída varia sutilmente.

Conversão e coerção de tipos (Type Casting)

A conversão de tipo (type casting) converte um valor de um tipo de dados para outro, o que é essencial quando dados de diferentes fontes precisam ser combinados ou quando você precisa alterar a forma como um valor é interpretado.

A conversão implícita acontece automaticamente quando o banco de dados converte tipos para viabilizar uma operação. INSERT INTO table_name (int_column) VALUES ('123') pode converter implicitamente a string '123' no número inteiro 123. A conversão implícita é conveniente, mas arriscada — o banco de dados pode realizar conversões que você não pretendia, ou a conversão pode falhar silenciosamente, gerando resultados inesperados.

A conversão explícita usando CAST ou CONVERT oferece controle preciso e deixa suas intenções claras para outros desenvolvedores. A conversão explícita evita surpresas silenciosas e torna o desempenho da consulta mais previsível.

As conversões comuns incluem a conversão de strings em números para cálculos, conversão de números em strings para concatenação e conversão para DATE ou TIMESTAMP para filtrar por intervalos temporais.

Exemplo de uso do CAST:

Essas conversões explícitas deixam o código claro: qualquer pessoa que leia a consulta entende imediatamente que a conversão está ocorrendo e sabe exatamente qual tipo é gerado.

Tipos de dados entre fornecedores de bancos de dados

Os tipos de dados SQL variam entre MySQL, PostgreSQL, SQL Server e Oracle. Embora os conceitos fundamentais (numérico, caractere, data/hora, binário) sejam universais, os nomes específicos dos tipos, a precisão e as características de armazenamento diferem.

O MySQL usa TINYINT para valores booleanos (mapeando BOOLEAN como um alias para TINYINT(1)), VARCHAR para strings variáveis e BLOB para dados binários. O PostgreSQL suporta BOOLEAN nativamente, TEXT para textos grandes sem limites de tamanho e BYTEA para dados binários. O SQL Server usa INT e BIGINT como a maioria dos bancos de dados, VARCHAR para strings e IMAGE para dados binários grandes. O Oracle possui NUMBER para valores numéricos, VARCHAR2 para strings (não VARCHAR) e BLOB para dados binários.

Essas diferenças são importantes ao migrar esquemas. Uma coluna TEXT do PostgreSQL pode conter qualquer quantidade de dados, mas o TEXT do MySQL tem um limite de 64 KB e exige LONGTEXT para conteúdos maiores. O VARCHAR(MAX) do SQL Server é necessário para textos realmente grandes, enquanto o TEXT do PostgreSQL lida com isso diretamente. O tipo NUMBER do Oracle é mais flexível do que os tipos numéricos da maioria dos bancos de dados, permitindo que você especifique a precisão e a escala de forma diferente.

Consulte a documentação oficial do seu banco de dados antes de projetar esquemas que devem ser portáveis. Teste seus dados reais com o sistema de banco de dados de destino para identificar casos extremos em que as suposições sobre o comportamento dos tipos não se confirmam.

Boas práticas para tipos de dados

Prefira tipos de precisão fixa, como DECIMAL, para dados financeiros, evitando totalmente tipos de ponto flutuante em sistemas de contabilidade ou faturamento. A precisão financeira é inegociável, e a exatidão do DECIMAL compensa o pequeno custo de desempenho. Organizações que constroem sistemas de análise em plataformas modernas de data warehouse priorizam cada vez mais a seleção adequada de tipos de dados como base para governança e desempenho.

Evite usar strings para datas ou booleanos, mesmo que isso seja tecnicamente possível. Armazenar datas como VARCHAR dificulta a aritmética de datas, impede que o banco de dados otimize consultas baseadas em datas e torna a validação mais difícil. Armazenar booleanos como strings introduz ambiguidade — "false" é o mesmo que "no"? — e desperdiça armazenamento. Use tipos nativos DATE, TIMESTAMP e BOOLEAN, que foram criados especificamente para esses valores.

Revise e otimize os tipos durante as auditorias de esquema, especialmente quando os bancos de dados já existem há anos e os padrões de uso mudaram. Uma coluna definida como VARCHAR(1000) por motivos que não se aplicam mais desperdiça espaço em cada linha. Use o EXPLAIN PLAN ou as ferramentas de análise de consulta do seu banco de dados para identificar consultas lentas causadas por escolhas incorretas de tipo e, em seguida, faça a refatoração.

Documente suas escolhas de tipo, especialmente casos extremos e suposições. Um comentário explicando por que uma coluna é TINYINT em vez de INT evita que alguém a altere mais tarde com base em um entendimento incompleto. Essa documentação é particularmente importante para tipos numéricos em que o intervalo é relevante.

Perguntas frequentes

Qual é a diferença entre CHAR e VARCHAR?

O CHAR armazena strings de comprimento fixo e sempre usa o tamanho total declarado, preenchendo com espaços. O VARCHAR armazena strings de comprimento variável e usa apenas o espaço necessário para os dados reais. O CHAR é mais eficiente para dados de tamanho fixo, como códigos de países (sempre 2 letras), enquanto o VARCHAR é mais eficiente para dados de comprimento variável, como nomes. Os tipos de dados de string impõem regras na inserção de dados em colunas SQL, e a escolha entre CHAR e VARCHAR afeta tanto o armazenamento quanto o desempenho no seu sistema de banco de dados.

Quando devo usar DECIMAL em vez de FLOAT?

O DECIMAL armazena valores exatos e evita erros de arredondamento, sendo essencial para dados financeiros onde a precisão é fundamental. O FLOAT armazena valores aproximados de forma mais rápida, mas introduz artefatos de arredondamento. Use DECIMAL para valores monetários, medições científicas precisas e cálculos em que a exatidão seja auditável. Use FLOAT para aproximações, recursos de machine learning e computação científica onde pequenos erros são aceitáveis. Escolher o tipo de dados correto é essencial para a integridade dos dados em sistemas financeiros.

Como escolher entre DATE e TIMESTAMP?

Use DATE quando precisar apenas registrar a data do calendário sem informações de hora, como a data de nascimento de um cliente ou a data de uma transação. Use TIMESTAMP quando precisar de informações temporais precisas, incluindo horas, minutos e segundos, como carimbos de data/hora de eventos ou horários de conclusão de transações. Os tipos de data e hora são usados para registrar quando os eventos acontecem, e a seleção do tipo correto simplifica as consultas e evita o desperdício de armazenamento.

Quais são os comprimentos máximos para tipos de dados de caracteres?

Os comprimentos máximos variam de acordo com o banco de dados. O VARCHAR normalmente suporta comprimentos de até 65.535 bytes no MySQL, ilimitado no PostgreSQL e até 8.000 bytes no SQL Server (ou VARCHAR(MAX) para valores maiores). Sempre verifique a documentação do seu banco de dados específico para obter os limites exatos. A escolha de tipos apropriados pode melhorar a escalabilidade a longo prazo e evitar atingir limites inesperados de armazenamento.

Como devo lidar com fusos horários no meu banco de dados?

Armazene todos os timestamps em UTC para garantir consistência e comparabilidade. Converta os timestamps para UTC antes de armazenar e de volta para o fuso horário local do usuário ao exibir. Alguns bancos de dados como o PostgreSQL oferecem suporte a TIMESTAMPTZ para lidar automaticamente com essa conversão. O tratamento consistente de fuso horário evita bugs em cálculos baseados em tempo e torna a ordenação de eventos inequívoca.

Qual tipo de dados devo usar para identificadores exclusivos?

Os valores de UUID normalmente usam BINARY(16) para armazenamento de tamanho fixo ou CHAR(36) para a representação de string padrão, incluindo hífens. Alguns bancos de dados como o PostgreSQL oferecem suporte a tipos UUID nativos. INT ou BIGINT funcionam para IDs numéricos de incremento automático. Escolha com base no seu esquema de identificação — IDs numéricos sequenciais são simples, mas facilitam a adivinhação de IDs, enquanto os UUIDs são aleatórios e adequados para sistemas distribuídos.

Por que a escolha do tipo de dados é importante para o desempenho de consultas?

Tipos de dados menores acomodam mais linhas no cache da CPU, tornando as consultas mais rápidas. Os índices são mais eficazes em tipos numéricos de tamanho adequado. A eficiência de armazenamento reduz o I/O de disco e melhora a latência das consultas. O desempenho das consultas melhora com o uso de tipos de dados de tamanho adequado, e escolher o menor tipo que armazena seus dados com segurança mantém os bancos de dados rápidos e enxutos.

(Esta publicação no blog foi traduzida utilizando ferramentas baseadas em inteligência artificial) Publicação original

Receba os posts mais recentes na sua caixa de entrada

Assine nosso blog e receba os posts mais recentes diretamente na sua caixa de entrada.