Strings sujas sao a realidade diaria de quem analisa dados: espacos extras vindos de importacoes, telefones cheios de tracos, codigos com maiusculas e minusculas misturadas. Tres funcoes — TRIM, SUBSTRING e REPLACE — resolvem quase toda essa limpeza rotineira. Vamos exercita-las sobre um esquema com users(id, email, name, country, created_at), orders(id, user_id, amount, status, created_at) e employees(id, name, manager_id, dept, salary).
TRIM: cortar espacos e lixo
Por padrao, o TRIM remove espacos das duas pontas. E a primeira coisa a aplicar em qualquer campo de texto vindo de uma fonte externa.
SELECT TRIM(name) AS clean_name
FROM users;
Voce pode aparar apenas um lado e ate informar seu proprio conjunto de caracteres:
SELECT TRIM(LEADING FROM name) AS no_left,
TRIM(TRAILING FROM name) AS no_right
FROM users;
SELECT TRIM(BOTH '0' FROM '00description') AS no_zeros;
Parentes uteis: LTRIM e RTRIM para aparar so um lado, e BTRIM no PostgreSQL como sinonimo curto de TRIM(BOTH ...).
- O
TRIM so remove os caracteres das extremidades, nunca os internos: 'a b' mantem o espaco duplo no meio.
- Caracteres invisiveis — tabulacoes (
\t), quebras de linha, o espaco inquebravel — ficam intactos com um TRIM simples. Para esses, combine com REPLACE ou REGEXP_REPLACE.
SUBSTRING: fatiar por posicao
SUBSTRING extrai um pedaco de uma string. A sintaxe padrao canonica usa as palavras-chave FROM (inicio, comecando em 1) e FOR (comprimento):
SELECT SUBSTRING(country FROM 1 FOR 3) AS region_prefix
FROM users;
A forma posicional com virgulas da o mesmo resultado; e mais curta e familiar para muita gente:
SELECT SUBSTRING(country, 1, 3) AS region_prefix
FROM users;
Um truque comum e pegar o dominio de um email localizando a posicao do @ com POSITION:
SELECT SUBSTRING(email FROM POSITION('@' IN email) + 1) AS domain
FROM users;
REPLACE: trocar substrings
REPLACE(source, from, to) substitui TODAS as ocorrencias de um literal. E perfeito para remover formatacao — por exemplo, transformar um telefone em digitos limpos:
SELECT REPLACE(REPLACE(name, '-', ''), ' ', '') AS compact
FROM users;
O REPLACE trabalha apenas com strings literais, sem padroes. Se voce precisa de expressoes regulares, use REGEXP_REPLACE no PostgreSQL:
SELECT REGEXP_REPLACE(name, '[^0-9]', '', 'g') AS digits_only
FROM users;
Montando uma chave normalizada
A forca real esta em combinar tudo isso. Uma tarefa tipica e montar uma chave estavel para deduplicacao ou joins: tudo minusculo, sem espacos, sem separadores.
SELECT o.id,
LOWER(TRIM(u.country)) || '_' ||
REPLACE(LOWER(o.status), ' ', '_') AS norm_key
FROM orders o
JOIN users u ON u.id = o.user_id;
Para um relatorio por departamento, voce pode montar um codigo organizado a partir do nome e do departamento:
SELECT id,
UPPER(SUBSTRING(TRIM(dept) FROM 1 FOR 3)) || '-' ||
UPPER(SUBSTRING(TRIM(name) FROM 1 FOR 2)) AS emp_code
FROM employees;
Diferencas entre os bancos
- PostgreSQL: aceita tanto
SUBSTRING(x FROM a FOR b) quanto SUBSTRING(x, a, b); SUBSTR existe como sinonimo. Comeca em 1.
- MySQL:
SUBSTRING e SUBSTR sao equivalentes, e a sintaxe FROM ... FOR tambem funciona. Aceita inicio negativo — contando de tras para frente a partir do fim da string.
- ClickHouse: a funcao e
substring(s, offset, length), apenas na forma posicional; replaceAll no lugar de REPLACE, e trimBoth/trimLeft/trimRight no lugar de TRIM.
A grande pegadinha: a indexacao de strings no SQL comeca em 1, e nao em 0. SUBSTRING(x FROM 0 FOR 3) se comporta de forma pouco intuitiva — a posicao zero consome um caractere do comprimento. Conte sempre a partir de um e FROM 1 FOR n lhe dara exatamente os primeiros n caracteres.
Strings sujas sao a realidade diaria de quem analisa dados: espacos extras vindos de importacoes, telefones cheios de tracos, codigos com maiusculas e minusculas misturadas. Tres funcoes —
TRIM,SUBSTRINGeREPLACE— resolvem quase toda essa limpeza rotineira. Vamos exercita-las sobre um esquema comusers(id, email, name, country, created_at),orders(id, user_id, amount, status, created_at)eemployees(id, name, manager_id, dept, salary).TRIM: cortar espacos e lixo
Por padrao, o
TRIMremove espacos das duas pontas. E a primeira coisa a aplicar em qualquer campo de texto vindo de uma fonte externa.SELECT TRIM(name) AS clean_name FROM users;Voce pode aparar apenas um lado e ate informar seu proprio conjunto de caracteres:
-- Leading vs trailing SELECT TRIM(LEADING FROM name) AS no_left, TRIM(TRAILING FROM name) AS no_right FROM users; -- Strip a specific character, not just spaces SELECT TRIM(BOTH '0' FROM '00description') AS no_zeros; -- 'description'Parentes uteis:
LTRIMeRTRIMpara aparar so um lado, eBTRIMno PostgreSQL como sinonimo curto deTRIM(BOTH ...).TRIMso remove os caracteres das extremidades, nunca os internos:'a b'mantem o espaco duplo no meio.\t), quebras de linha, o espaco inquebravel — ficam intactos com umTRIMsimples. Para esses, combine comREPLACEouREGEXP_REPLACE.SUBSTRING: fatiar por posicao
SUBSTRINGextrai um pedaco de uma string. A sintaxe padrao canonica usa as palavras-chaveFROM(inicio, comecando em 1) eFOR(comprimento):-- First 3 chars of the country code SELECT SUBSTRING(country FROM 1 FOR 3) AS region_prefix FROM users;A forma posicional com virgulas da o mesmo resultado; e mais curta e familiar para muita gente:
SELECT SUBSTRING(country, 1, 3) AS region_prefix FROM users;Um truque comum e pegar o dominio de um email localizando a posicao do
@comPOSITION:SELECT SUBSTRING(email FROM POSITION('@' IN email) + 1) AS domain FROM users;REPLACE: trocar substrings
REPLACE(source, from, to)substitui TODAS as ocorrencias de um literal. E perfeito para remover formatacao — por exemplo, transformar um telefone em digitos limpos:-- Strip dashes and spaces from a phone-like field SELECT REPLACE(REPLACE(name, '-', ''), ' ', '') AS compact FROM users;O REPLACE trabalha apenas com strings literais, sem padroes. Se voce precisa de expressoes regulares, use
REGEXP_REPLACEno PostgreSQL:-- Keep digits only SELECT REGEXP_REPLACE(name, '[^0-9]', '', 'g') AS digits_only FROM users;Montando uma chave normalizada
A forca real esta em combinar tudo isso. Uma tarefa tipica e montar uma chave estavel para deduplicacao ou joins: tudo minusculo, sem espacos, sem separadores.
-- A normalized join key from country + status SELECT o.id, LOWER(TRIM(u.country)) || '_' || REPLACE(LOWER(o.status), ' ', '_') AS norm_key FROM orders o JOIN users u ON u.id = o.user_id;Para um relatorio por departamento, voce pode montar um codigo organizado a partir do nome e do departamento:
SELECT id, UPPER(SUBSTRING(TRIM(dept) FROM 1 FOR 3)) || '-' || UPPER(SUBSTRING(TRIM(name) FROM 1 FOR 2)) AS emp_code FROM employees;Diferencas entre os bancos
SUBSTRING(x FROM a FOR b)quantoSUBSTRING(x, a, b);SUBSTRexiste como sinonimo. Comeca em 1.SUBSTRINGeSUBSTRsao equivalentes, e a sintaxeFROM ... FORtambem funciona. Aceita inicio negativo — contando de tras para frente a partir do fim da string.substring(s, offset, length), apenas na forma posicional;replaceAllno lugar deREPLACE, etrimBoth/trimLeft/trimRightno lugar deTRIM.A grande pegadinha: a indexacao de strings no SQL comeca em 1, e nao em 0.
SUBSTRING(x FROM 0 FOR 3)se comporta de forma pouco intuitiva — a posicao zero consome um caractere do comprimento. Conte sempre a partir de um eFROM 1 FOR nlhe dara exatamente os primeirosncaracteres.