CNPJ alfanumérico no banco: MySQL e PostgreSQL
Como adaptar a coluna de CNPJ no MySQL e no PostgreSQL ao formato alfanumérico: ALTER TABLE para VARCHAR, cuidados com comparação, ordenação, índices e máscara do formulário.
Guardar CNPJ alfanumérico no banco de dados começa com uma decisão simples: a coluna precisa ser texto, nunca número. Se hoje você usa INT, BIGINT ou ZEROFILL, o novo formato vai quebrar — as letras das 12 primeiras posições não cabem em campo numérico. Este tutorial mostra o ALTER TABLE certo para MySQL e PostgreSQL, os cuidados com comparação, ordenação e índices, e como ajustar a máscara do formulário.
O que muda no CNPJ alfanumérico
A partir de julho de 2026, o novo CNPJ alfanumérico mantém as 14 posições e a mesma máscara XX.XXX.XXX/XXXX-DD, mas as 12 primeiras posições (raiz + ordem) passam a aceitar letras maiúsculas A–Z além dos dígitos 0–9. Os dois últimos caracteres (dígitos verificadores) continuam numéricos. Os CNPJs numéricos atuais não mudam e seguem válidos, então seu banco precisa armazenar e comparar os dois formatos ao mesmo tempo. Para o panorama completo, veja o nosso guia de implementação do CNPJ alfanumérico.
O erro nº 1: guardar CNPJ como número
O problema mais comum em sistemas brasileiros é a coluna de CNPJ ter sido criada como inteiro. Funcionava enquanto o CNPJ era só dígito, mas tinha bugs silenciosos (zeros à esquerda some, 00.000.123/... vira 123) e agora simplesmente não aceita letras. Um CNPJ ABC1234D56... gravado em BIGINT resulta em 0, erro de truncamento ou exceção, dependendo do banco.
Migrando a coluna: ALTER TABLE
A recomendação é guardar o CNPJ sem máscara, com 14 caracteres, sempre em maiúsculas. Se você optar por gravar com máscara, use largura 18. Abaixo, o ALTER TABLE para cada banco — rode antes de julho de 2026, num horário de baixo tráfego, e com backup feito.
-- guarde sem máscara, 14 caracteres, sempre maiúsculo
ALTER TABLE clientes MODIFY cnpj VARCHAR(14) NULL; -- MySQL
ALTER TABLE clientes ALTER COLUMN cnpj TYPE varchar(14); -- PostgreSQLNo MySQL, MODIFY reescreve a definição inteira da coluna — repita os atributos que quer manter (por exemplo NULL/NOT NULL). No PostgreSQL, se a coluna atual for inteira, o TYPE varchar(14) precisa de uma conversão explícita; use USING para não perder os dados existentes:
-- PostgreSQL: convertendo de inteiro para texto sem perder o que já existe
ALTER TABLE clientes
ALTER COLUMN cnpj TYPE varchar(14)
USING lpad(cnpj::text, 14, '0');Comparação, ordenação e índices
Depois de virar texto, ajuste as consultas. Buscas devem usar a string normalizada — sempre maiúscula e sem máscara — para casar com o que está gravado:
-- certo: compara como texto, já normalizado pela aplicação
SELECT * FROM clientes WHERE cnpj = 'ABC1234D5601' || '...';
-- errado: nunca compare como número
-- SELECT * FROM clientes WHERE cnpj = 12345678000190;A ordenação passa a ser alfabética (lexicográfica), o que é o esperado para um identificador alfanumérico — não tente reproduzir ordem numérica. Para o índice, um VARCHAR(14) indexa normalmente e a busca por igualdade continua rápida. Se a sua coluna pode receber valores em caixas diferentes por causa de dados legados, garanta a normalização na escrita (gravar sempre em maiúsculas) ou crie um índice funcional sobre UPPER(cnpj) no PostgreSQL:
-- PostgreSQL: índice funcional para buscas case-insensitive
CREATE INDEX idx_clientes_cnpj_upper ON clientes (UPPER(cnpj));
-- MySQL: a melhor estratégia é gravar já em maiúsculas
CREATE INDEX idx_clientes_cnpj ON clientes (cnpj);Ajustando a máscara e a validação no formulário
No front-end, o erro espelha o do banco: máscaras e validações que só aceitam dígitos. Troque type="number" por type="text", force maiúsculas com CSS e use uma expressão regular que aceite letras nas 12 primeiras posições. Nunca use \d para a base inteira.
<input
type="text"
name="cnpj"
maxlength="18"
inputmode="text"
style="text-transform: uppercase"
placeholder="XX.XXX.XXX/XXXX-DD"
>Na validação do lado do cliente, use o padrão com máscara ou só os 14 caracteres. Letras nas 12 primeiras, dígitos nos dois verificadores:
// com máscara: XX.XXX.XXX/XXXX-DD
const FORMATO_MASCARA = /^[A-Z0-9]{2}\.[A-Z0-9]{3}\.[A-Z0-9]{3}\/[A-Z0-9]{4}-\d{2}$/;
// só caracteres (o que vai pro banco): 12 alfanuméricos + 2 dígitos
const FORMATO_LIMPO = /^[A-Z0-9]{12}\d{2}$/;
// normalize SEMPRE antes de gravar: maiúsculas, sem máscara
const normalizar = (s) => (s || '').toUpperCase().replace(/[^A-Z0-9]/g, '');Repare que a diferença para o código antigo é trocar \d por [A-Z0-9] nas 12 primeiras posições e aplicar toUpperCase() na normalização. O valor que chega ao banco é o resultado de normalizar(): 14 caracteres, maiúsculos, sem pontuação.
Como testar
- Trocar todas as colunas de CNPJ de
INT/BIGINT/ZEROFILLparaVARCHAR(14)(ou 18 com máscara). - Rodar o
UPDATEde normalização: maiúsculas e sem máscara nos dados existentes. - Remover comparações numéricas (
= 12345) e qualquerORDER BYque assuma ordem numérica. - Garantir gravação em MAIÚSCULAS na aplicação; criar índice funcional
UPPER(cnpj)se houver dados em caixas diferentes. - Atualizar o formulário:
type="text",text-transform: uppercase, regex com[A-Z0-9]em vez de\d. - Auditar integrações, NF-e e contratos de API para aceitar letras; manter a convivência com os CNPJs numéricos atuais.
Para gerar massa de teste e popular o banco, use o nosso gerador de CNPJ alfanumérico e confira cada valor no validador de CNPJ alfanumérico.
| CNPJ | Tipo | Esperado |
|---|---|---|
12.ABC.345/01DE-35 | Alfanumérico (filial) | válido |
XP.TO1.234/0001-20 | Alfanumérico (matriz) | válido |
9F.8E7.D6C/0001-36 | Alfanumérico (matriz) | válido |
A1.B2C.3D4/E5F6-68 | Alfanumérico (filial) | válido |
ZZ.ZZ0.001/AAAA-41 | Alfanumérico | válido |
11.222.333/0001-81 | Numérico clássico | válido |
12.ABC.345/01DE-34 | DV incorreto | inválido |
Perguntas frequentes
Posso continuar usando coluna numérica e converter na aplicação?
Não. Um CNPJ alfanumérico como 12ABC34501DE35 não é representável em INT ou BIGINT — a conversão descarta as letras ou estoura. A única coluna correta é texto (VARCHAR(14) sem máscara), e a normalização (maiúsculas, sem pontuação) deve acontecer na aplicação antes de gravar.
VARCHAR(14) ou VARCHAR(18)?
Use VARCHAR(14) se guardar sem máscara, que é a recomendação: são exatamente 14 posições. Se você precisa armazenar com a máscara XX.XXX.XXX/XXXX-DD, aí são 18 caracteres. Guardar sem máscara facilita índices, comparações e a convivência com os CNPJs numéricos atuais.
Como faço a validação do CNPJ antes de gravar?
A validação (módulo 11 com ASCII − 48) roda na aplicação, não no banco. Veja as funções prontas em PHP e JavaScript — elas já normalizam para maiúsculas e devolvem a string de 14 caracteres pronta para o VARCHAR.
Os CNPJs numéricos que já estão no banco continuam válidos?
Continuam. Os numéricos atuais não mudam e seguem em uso ao lado dos novos. Como a coluna vira texto, ela aceita os dois formatos sem qualquer perda — basta garantir que comparações e índices tratem o campo como string.
Fontes: Receita Federal (IN RFB 2.229/2024) e nota técnica do Serpro sobre o CNPJ alfanumérico.
Ofertas em destaque
Ver todas →
Amazon
-27%
Hellmann's Maionese Light 500g
Mercado Livre
Kit 10 Pares Meia Invisível Unissex Soquete Algodão Selene 10 Branco Original Soquete Cano Curto G ( 39 A 44 )
Shopee
-60%
Brow Rise Gel Para Sobrancelhas By Ruby Rose Linha Rosa HB-E2503 Hot Sale
Shopee
-56%
Calça Pantalona Lanzinha Feminina Cintura Alta Com Elastico De e Bolso Outono / Inverno Promoção
Amazon
-93%
Tramontina Ducha Elétrica 3 Temperaturas 5500 W 127 V Chuveiro Branco
Amazon
Leite em Pó Ninho Integral Instantâneo Sachê 975g
Mercado Livre
Perfume Lattafa Bade'e Al Oud For Glory Edp Spray 100 Ml
Amazon
-14%
Lenços Umedecidos Huggies Rosto e Corpo Limpeza 4 x 48 Un
Shopee
-33%