Strings sujas sao o normal: espacos extras vindos de formularios, zeros a esquerda em codigos, barras no fim de URLs. BTRIM, LTRIM e RTRIM removem caracteres das bordas de uma string e resolvem a maioria desses casos com uma unica funcao.
As tres compartilham uma propriedade essencial: cortam apenas nas bordas e nunca tocam o miolo. BTRIM('a b', ' ') devolve 'a b' sem alteracao — os espacos entre as palavras permanecem, somente os iniciais e finais saem. Isso as distingue de REPLACE, que apagaria os espacos da string inteira. Por padrao as tres removem espacos, mas um segundo argumento permite indicar qualquer conjunto de caracteres — zeros, barras, hifens, simbolos de moeda — e essa flexibilidade e a maior vantagem sobre o TRIM padrao puro.
Tres funcoes e o que cada uma corta
No PostgreSQL a familia e simetrica:
LTRIM(s) — remove caracteres a esquerda (no inicio);
RTRIM(s) — remove caracteres a direita (no fim);
BTRIM(s) — remove das duas pontas.
Por padrao removem espacos. Mas cada funcao aceita um segundo argumento: o conjunto de caracteres a remover.
SELECT
LTRIM(' hello ') AS left_only,
RTRIM(' hello ') AS right_only,
BTRIM(' hello ') AS both_sides;
Um ponto importante: o segundo argumento nao e uma substring, e um conjunto de caracteres. BTRIM('xxyhelloyxx', 'xy') remove qualquer caractere inicial e final que pertenca a {'x','y'}, em qualquer ordem, ate encontrar algo diferente.
Normalizando dados de usuario
O caso mais comum e limpar email e name antes de inserir ou comparar. Espacos nas bordas quebram a unicidade e os joins.
SELECT id, BTRIM(LOWER(email)) AS email_clean
FROM users
WHERE BTRIM(email) <> '';
UPDATE users
SET name = BTRIM(name)
WHERE name <> BTRIM(name);
O predicado name <> BTRIM(name) atualiza apenas as linhas realmente sujas: e mais barato e evita encher o log com atualizacoes sem efeito.
Removendo caracteres arbitrarios: zeros e barras
Aqui o conjunto de caracteres mostra todo o seu valor. Vamos tirar zeros a esquerda de um codigo e a barra final de um caminho.
SELECT
LTRIM('00042', '0') AS code,
RTRIM('https://shop.dev/api/', '/') AS endpoint,
BTRIM('--draft--', '-') AS status;
Um exemplo pratico sobre orders: os status as vezes chegam com marcadores de envolucro, e os valores vem como texto com simbolo de moeda.
SELECT
id,
BTRIM(status, '*') AS status,
LTRIM(CAST(amount AS text), '$') AS amount_text
FROM orders
WHERE status LIKE '%*%';
BTRIM/LTRIM/RTRIM sao nomes do dialeto do PostgreSQL. O padrao SQL define um unico operador TRIM com palavras-chave de direcao:
SELECT
TRIM(LEADING '0' FROM '00042') AS a,
TRIM(TRAILING '/' FROM 'path/') AS b,
TRIM(BOTH ' ' FROM ' x ') AS c;
A correspondencia e exata:
TRIM(LEADING c FROM s) = LTRIM(s, c);
TRIM(TRAILING c FROM s) = RTRIM(s, c);
TRIM(BOTH c FROM s) = BTRIM(s, c).
Uma sutileza: no padrao SQL o caractere de corte e um unico caractere, enquanto em BTRIM/LTRIM o segundo argumento e um conjunto de caracteres. O PostgreSQL estende o TRIM para aceitar esse mesmo conjunto, entao TRIM(BOTH 'xy' FROM s) remove qualquer x ou y das bordas, igual a BTRIM(s, 'xy'). Para "remover qualquer um destes caracteres" a forma *TRIM (ou o TRIM do PostgreSQL) se encaixa melhor, mas nao suponha que todo motor le esse argumento da mesma maneira.
Diferencas no MySQL e no ClickHouse
- MySQL: existem
TRIM, LTRIM, RTRIM, mas LTRIM/RTRIM nao aceitam segundo argumento: removem apenas espacos. Nao ha BTRIM; use TRIM(BOTH 'x' FROM s), mas lembre que aqui o argumento e uma substring (remstr), nao um conjunto de caracteres.
- ClickHouse: tem
trimLeft, trimRight, trimBoth, mas eles tambem removem apenas espacos. Para caracteres arbitrarios use trim(LEADING 'x' FROM s) ou uma expressao regular como replaceRegexpOne.
A maior armadilha e confundir "conjunto de caracteres" com "substring". RTRIM('abcxyz', 'zyx') no PostgreSQL retorna 'abc' porque corta do fim cada caractere do conjunto {z,y,x}, um a um, sem importar a ordem. TRIM(TRAILING 'zyx' FROM 'abcxyz') no MySQL retorna a string intacta, porque a substring literal 'zyx' nao casa no fim; apenas 'xyz' casaria como substring inteira. Troque a ordem das letras e o resultado do MySQL muda, enquanto o do PostgreSQL nao. Confirme sempre se o seu motor trata o argumento como um conjunto de caracteres ou como uma substring.
Strings sujas sao o normal: espacos extras vindos de formularios, zeros a esquerda em codigos, barras no fim de URLs.
BTRIM,LTRIMeRTRIMremovem caracteres das bordas de uma string e resolvem a maioria desses casos com uma unica funcao.As tres compartilham uma propriedade essencial: cortam apenas nas bordas e nunca tocam o miolo.
BTRIM('a b', ' ')devolve'a b'sem alteracao — os espacos entre as palavras permanecem, somente os iniciais e finais saem. Isso as distingue deREPLACE, que apagaria os espacos da string inteira. Por padrao as tres removem espacos, mas um segundo argumento permite indicar qualquer conjunto de caracteres — zeros, barras, hifens, simbolos de moeda — e essa flexibilidade e a maior vantagem sobre oTRIMpadrao puro.Tres funcoes e o que cada uma corta
No PostgreSQL a familia e simetrica:
LTRIM(s)— remove caracteres a esquerda (no inicio);RTRIM(s)— remove caracteres a direita (no fim);BTRIM(s)— remove das duas pontas.Por padrao removem espacos. Mas cada funcao aceita um segundo argumento: o conjunto de caracteres a remover.
SELECT LTRIM(' hello ') AS left_only, -- 'hello ' RTRIM(' hello ') AS right_only, -- ' hello' BTRIM(' hello ') AS both_sides; -- 'hello'Um ponto importante: o segundo argumento nao e uma substring, e um conjunto de caracteres.
BTRIM('xxyhelloyxx', 'xy')remove qualquer caractere inicial e final que pertenca a{'x','y'}, em qualquer ordem, ate encontrar algo diferente.Normalizando dados de usuario
O caso mais comum e limpar
emailenameantes de inserir ou comparar. Espacos nas bordas quebram a unicidade e os joins.-- Normalize on read SELECT id, BTRIM(LOWER(email)) AS email_clean FROM users WHERE BTRIM(email) <> ''; -- Fix existing rows in place UPDATE users SET name = BTRIM(name) WHERE name <> BTRIM(name);O predicado
name <> BTRIM(name)atualiza apenas as linhas realmente sujas: e mais barato e evita encher o log com atualizacoes sem efeito.Removendo caracteres arbitrarios: zeros e barras
Aqui o conjunto de caracteres mostra todo o seu valor. Vamos tirar zeros a esquerda de um codigo e a barra final de um caminho.
SELECT LTRIM('00042', '0') AS code, -- '42' RTRIM('https://shop.dev/api/', '/') AS endpoint,-- 'https://shop.dev/api' BTRIM('--draft--', '-') AS status; -- 'draft'Um exemplo pratico sobre
orders: os status as vezes chegam com marcadores de envolucro, e os valores vem como texto com simbolo de moeda.SELECT id, BTRIM(status, '*') AS status, LTRIM(CAST(amount AS text), '$') AS amount_text FROM orders WHERE status LIKE '%*%';Relacao com o TRIM padrao
BTRIM/LTRIM/RTRIMsao nomes do dialeto do PostgreSQL. O padrao SQL define um unico operadorTRIMcom palavras-chave de direcao:SELECT TRIM(LEADING '0' FROM '00042') AS a, -- same as LTRIM('00042','0') TRIM(TRAILING '/' FROM 'path/') AS b, -- same as RTRIM('path/','/') TRIM(BOTH ' ' FROM ' x ') AS c; -- same as BTRIM(' x ')A correspondencia e exata:
TRIM(LEADING c FROM s)=LTRIM(s, c);TRIM(TRAILING c FROM s)=RTRIM(s, c);TRIM(BOTH c FROM s)=BTRIM(s, c).Uma sutileza: no padrao SQL o caractere de corte e um unico caractere, enquanto em
BTRIM/LTRIMo segundo argumento e um conjunto de caracteres. O PostgreSQL estende oTRIMpara aceitar esse mesmo conjunto, entaoTRIM(BOTH 'xy' FROM s)remove qualquerxouydas bordas, igual aBTRIM(s, 'xy'). Para "remover qualquer um destes caracteres" a forma*TRIM(ou oTRIMdo PostgreSQL) se encaixa melhor, mas nao suponha que todo motor le esse argumento da mesma maneira.Diferencas no MySQL e no ClickHouse
TRIM,LTRIM,RTRIM, masLTRIM/RTRIMnao aceitam segundo argumento: removem apenas espacos. Nao haBTRIM; useTRIM(BOTH 'x' FROM s), mas lembre que aqui o argumento e uma substring (remstr), nao um conjunto de caracteres.trimLeft,trimRight,trimBoth, mas eles tambem removem apenas espacos. Para caracteres arbitrarios usetrim(LEADING 'x' FROM s)ou uma expressao regular comoreplaceRegexpOne.A maior armadilha e confundir "conjunto de caracteres" com "substring".
RTRIM('abcxyz', 'zyx')no PostgreSQL retorna'abc'porque corta do fim cada caractere do conjunto{z,y,x}, um a um, sem importar a ordem.TRIM(TRAILING 'zyx' FROM 'abcxyz')no MySQL retorna a string intacta, porque a substring literal'zyx'nao casa no fim; apenas'xyz'casaria como substring inteira. Troque a ordem das letras e o resultado do MySQL muda, enquanto o do PostgreSQL nao. Confirme sempre se o seu motor trata o argumento como um conjunto de caracteres ou como uma substring.