Quando voce precisa dos tres primeiros digitos de um codigo ou dos quatro ultimos de um telefone, recorrer a um SUBSTRING prolixo e exagero. O PostgreSQL oferece duas funcoes curtas: LEFT pega caracteres do inicio da string e RIGHT pega do final. Vamos percorre-las na pratica e, de quebra, encontrar suas arestas afiadas.
Sintaxe basica
As duas funcoes recebem uma string e uma quantidade de caracteres: LEFT(string, n) e RIGHT(string, n). Elas contam caracteres, nao bytes, entao UTF-8 nao e problema.
SELECT LEFT('PROMO-2026', 5) AS head,
RIGHT('PROMO-2026', 4) AS tail;
Em uma tabela real isso e pratico para extrair prefixos e sufixos. Digamos que orders.status guarde uma string como paid-eu e voce queira as primeiras letras do status:
SELECT id,
LEFT(status, 4) AS status_head
FROM orders
LIMIT 5;
Propriedades principais:
- O tipo do resultado e
text.
- Se
n for maior que o comprimento da string, voce recebe a string inteira, sem erro e sem preenchimento.
- Uma entrada
NULL produz uma saida NULL.
Mascarar um numero de cartao
O caso classico e mostrar apenas os quatro ultimos digitos de um cartao de pagamento e esconder o resto. Aqui RIGHT e exatamente a ferramenta:
SELECT RIGHT('4111111111114242', 4) AS last4;
Para obter o formato familiar **** 4242, concatene uma mascara com a cauda. Suponha que exista uma coluna com o numero do cartao do usuario:
SELECT u.id,
'**** ' || RIGHT(card_number, 4) AS masked_card
FROM users u
JOIN payment_methods pm ON pm.user_id = u.id;
Da mesma forma, LEFT ajuda a extrair o BIN, os seis primeiros digitos que identificam o banco emissor:
SELECT LEFT(card_number, 6) AS bin
FROM payment_methods;
Gotcha: LEFT e RIGHT cortam caracteres, nao partes "logicas". Se o numero tiver espacos ou hifens (4111 1111 1111 4242), RIGHT(..., 4) retorna 4242 apenas se a cauda estiver limpa. Remova primeiro os separadores com REPLACE, senao voce pode mostrar por acidente um espaco em vez de um digito.
Comprimento negativo
Este e o recurso mais subestimado. Se voce passar um n negativo, o PostgreSQL conta caracteres a partir da ponta oposta e retorna o restante.
LEFT(s, -k) retorna a string sem seus ultimos k caracteres.
RIGHT(s, -k) retorna a string sem seus primeiros k caracteres.
SELECT LEFT('order-12345', -5) AS without_tail,
RIGHT('order-12345', -6) AS without_head;
Isso brilha quando voce conhece o comprimento da parte a cortar mas nao o da string. Por exemplo, remover um sufixo de dominio fixo ou tirar um prefixo conhecido. Mas cuidado: se -k for maior em modulo que o comprimento da string, voce recebe uma string vazia '', nao NULL, entao e facil perder dados em silencio.
LEFT e RIGHT versus SUBSTRING
SUBSTRING e mais poderoso, porem mais verboso. Qualquer LEFT/RIGHT pode ser expresso com ele:
SELECT SUBSTRING(name FROM 1 FOR 3) FROM users;
SELECT SUBSTRING(name FROM length(name) - 3 + 1) FROM users;
Repare que o equivalente de RIGHT obriga voce a calcular length() na mao e facilita erros de um a mais ou a menos. Entao a regra e simples:
- Precisa de um prefixo ou sufixo fixo: use
LEFT ou RIGHT, o codigo se le na hora.
- Precisa de um pedaco do meio ou uma posicao dinamica: use
SUBSTRING.
- Precisa cortar por um padrao em vez de por comprimento: olhe para
split_part ou expressoes regulares.
Um exemplo realista: agrupar funcionarios pela primeira letra do departamento com LEFT, bem mais limpo que SUBSTRING:
SELECT LEFT(dept, 1) AS dept_initial,
count(*) AS people
FROM employees
GROUP BY LEFT(dept, 1)
ORDER BY dept_initial;
MySQL e ClickHouse
Boa noticia: LEFT e RIGHT existem no MySQL com a mesma sintaxe LEFT(str, len) e RIGHT(str, len), entao as consultas migram quase sem ajustes.
- O MySQL nao suporta comprimento negativo:
LEFT('abc', -1) retorna uma string vazia, nao "tudo exceto o ultimo caractere". Essa e a diferenca principal ao migrar.
- O ClickHouse tambem tem
left e right; um argumento negativo ali funciona como no PostgreSQL, contando a partir do final.
- No MySQL as duas funcoes contam caracteres conforme o conjunto de caracteres atual da coluna, o que costuma coincidir com o comportamento do PostgreSQL para UTF-8.
SELECT LEFT(email, 3) AS prefix,
RIGHT(email, 3) AS suffix
FROM users;
Resumo: LEFT e RIGHT sao a forma mais rapida de pegar a borda de uma string. Lembre do comprimento negativo como "cortar pela outra ponta", sempre limpe os separadores antes de mascarar e tenha em mente que o argumento negativo nao funciona no MySQL.
Quando voce precisa dos tres primeiros digitos de um codigo ou dos quatro ultimos de um telefone, recorrer a um
SUBSTRINGprolixo e exagero. O PostgreSQL oferece duas funcoes curtas:LEFTpega caracteres do inicio da string eRIGHTpega do final. Vamos percorre-las na pratica e, de quebra, encontrar suas arestas afiadas.Sintaxe basica
As duas funcoes recebem uma string e uma quantidade de caracteres:
LEFT(string, n)eRIGHT(string, n). Elas contam caracteres, nao bytes, entao UTF-8 nao e problema.SELECT LEFT('PROMO-2026', 5) AS head, -- 'PROMO' RIGHT('PROMO-2026', 4) AS tail; -- '2026'Em uma tabela real isso e pratico para extrair prefixos e sufixos. Digamos que
orders.statusguarde uma string comopaid-eue voce queira as primeiras letras do status:SELECT id, LEFT(status, 4) AS status_head FROM orders LIMIT 5;Propriedades principais:
text.nfor maior que o comprimento da string, voce recebe a string inteira, sem erro e sem preenchimento.NULLproduz uma saidaNULL.Mascarar um numero de cartao
O caso classico e mostrar apenas os quatro ultimos digitos de um cartao de pagamento e esconder o resto. Aqui
RIGHTe exatamente a ferramenta:SELECT RIGHT('4111111111114242', 4) AS last4; -- '4242'Para obter o formato familiar
**** 4242, concatene uma mascara com a cauda. Suponha que exista uma coluna com o numero do cartao do usuario:SELECT u.id, '**** ' || RIGHT(card_number, 4) AS masked_card FROM users u JOIN payment_methods pm ON pm.user_id = u.id;Da mesma forma,
LEFTajuda a extrair o BIN, os seis primeiros digitos que identificam o banco emissor:SELECT LEFT(card_number, 6) AS bin FROM payment_methods;Gotcha:
LEFTeRIGHTcortam caracteres, nao partes "logicas". Se o numero tiver espacos ou hifens (4111 1111 1111 4242),RIGHT(..., 4)retorna4242apenas se a cauda estiver limpa. Remova primeiro os separadores comREPLACE, senao voce pode mostrar por acidente um espaco em vez de um digito.Comprimento negativo
Este e o recurso mais subestimado. Se voce passar um
nnegativo, o PostgreSQL conta caracteres a partir da ponta oposta e retorna o restante.LEFT(s, -k)retorna a string sem seus ultimoskcaracteres.RIGHT(s, -k)retorna a string sem seus primeiroskcaracteres.SELECT LEFT('order-12345', -5) AS without_tail, -- 'order-' RIGHT('order-12345', -6) AS without_head; -- '12345'Isso brilha quando voce conhece o comprimento da parte a cortar mas nao o da string. Por exemplo, remover um sufixo de dominio fixo ou tirar um prefixo conhecido. Mas cuidado: se
-kfor maior em modulo que o comprimento da string, voce recebe uma string vazia'', naoNULL, entao e facil perder dados em silencio.LEFT e RIGHT versus SUBSTRING
SUBSTRINGe mais poderoso, porem mais verboso. QualquerLEFT/RIGHTpode ser expresso com ele:-- LEFT(name, 3) is equivalent to: SELECT SUBSTRING(name FROM 1 FOR 3) FROM users; -- RIGHT(name, 3) is equivalent to: SELECT SUBSTRING(name FROM length(name) - 3 + 1) FROM users;Repare que o equivalente de
RIGHTobriga voce a calcularlength()na mao e facilita erros de um a mais ou a menos. Entao a regra e simples:LEFTouRIGHT, o codigo se le na hora.SUBSTRING.split_partou expressoes regulares.Um exemplo realista: agrupar funcionarios pela primeira letra do departamento com
LEFT, bem mais limpo queSUBSTRING:SELECT LEFT(dept, 1) AS dept_initial, count(*) AS people FROM employees GROUP BY LEFT(dept, 1) ORDER BY dept_initial;MySQL e ClickHouse
Boa noticia:
LEFTeRIGHTexistem no MySQL com a mesma sintaxeLEFT(str, len)eRIGHT(str, len), entao as consultas migram quase sem ajustes.LEFT('abc', -1)retorna uma string vazia, nao "tudo exceto o ultimo caractere". Essa e a diferenca principal ao migrar.lefteright; um argumento negativo ali funciona como no PostgreSQL, contando a partir do final.-- Works identically in PostgreSQL and MySQL SELECT LEFT(email, 3) AS prefix, RIGHT(email, 3) AS suffix FROM users;Resumo:
LEFTeRIGHTsao a forma mais rapida de pegar a borda de uma string. Lembre do comprimento negativo como "cortar pela outra ponta", sempre limpe os separadores antes de mascarar e tenha em mente que o argumento negativo nao funciona no MySQL.