sqlpostgresqlstringleft

LEFT y RIGHT en SQL: primeros y ultimos caracteres de una cadena en PostgreSQL

Como LEFT y RIGHT toman los primeros o ultimos N caracteres de una cadena en PostgreSQL: enmascarar tarjetas, prefijos, longitud negativa y comparacion con SUBSTRING.

3 min de lecturaReferencesql · postgresql · string · left · right · mysql

Cuando necesitas los tres primeros digitos de un codigo o los cuatro ultimos de un telefono, recurrir a un SUBSTRING verboso es excesivo. PostgreSQL ofrece dos funciones cortas: LEFT toma caracteres desde el inicio de la cadena y RIGHT los toma desde el final. Veamoslas en la practica y de paso descubramos sus bordes afilados.

Sintaxis basica

Ambas funciones reciben una cadena y un numero de caracteres: LEFT(string, n) y RIGHT(string, n). Cuentan caracteres, no bytes, asi que UTF-8 no da problemas.

SELECT LEFT('PROMO-2026', 5)  AS head,   -- 'PROMO'
       RIGHT('PROMO-2026', 4) AS tail;    -- '2026'

Sobre una tabla real esto es comodo para extraer prefijos y sufijos. Supongamos que orders.status guarda una cadena como paid-eu y queremos las primeras letras del estado:

SELECT id,
       LEFT(status, 4) AS status_head
FROM orders
LIMIT 5;

Propiedades clave:

  • El tipo del resultado es text.
  • Si n es mayor que la longitud de la cadena, recuperas la cadena entera, sin error y sin relleno.
  • Una entrada NULL produce una salida NULL.

Enmascarar un numero de tarjeta

El caso clasico es mostrar solo los cuatro ultimos digitos de una tarjeta de pago y ocultar el resto. Aqui RIGHT es justo la herramienta:

SELECT RIGHT('4111111111114242', 4) AS last4;   -- '4242'

Para obtener el formato habitual **** 4242, concatena una mascara con la cola. Supongamos que hay una columna con el numero de tarjeta del usuario:

SELECT u.id,
       '**** ' || RIGHT(card_number, 4) AS masked_card
FROM users u
JOIN payment_methods pm ON pm.user_id = u.id;

Del mismo modo, LEFT ayuda a extraer el BIN, los seis primeros digitos que identifican al banco emisor:

SELECT LEFT(card_number, 6) AS bin
FROM payment_methods;

Gotcha: LEFT y RIGHT cortan caracteres, no partes "logicas". Si el numero tiene espacios o guiones (4111 1111 1111 4242), RIGHT(..., 4) devuelve 4242 solo si la cola esta limpia. Elimina primero los separadores con REPLACE o podrias mostrar por accidente un espacio en lugar de un digito.

Longitud negativa

Esta es la opcion mas infravalorada. Si pasas un n negativo, PostgreSQL cuenta caracteres desde el extremo opuesto y devuelve el resto.

  • LEFT(s, -k) devuelve la cadena sin sus ultimos k caracteres.
  • RIGHT(s, -k) devuelve la cadena sin sus primeros k caracteres.
SELECT LEFT('order-12345', -5)  AS without_tail,   -- 'order-'
       RIGHT('order-12345', -6) AS without_head;     -- '12345'

Esto brilla cuando conoces la longitud de la parte que vas a recortar pero no la de la cadena. Por ejemplo, quitar un sufijo de dominio fijo o eliminar un prefijo conocido. Pero ten cuidado: si -k es mayor en magnitud que la longitud de la cadena, obtienes una cadena vacia '', no NULL, asi que es facil perder datos en silencio.

LEFT y RIGHT frente a SUBSTRING

SUBSTRING es mas potente pero mas verboso. Cualquier LEFT/RIGHT puede expresarse con el:

-- 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;

Fijate en que el equivalente de RIGHT te obliga a calcular length() a mano y facilita errores de uno en uno. Asi que la regla es simple:

  • Necesitas un prefijo o sufijo fijo: usa LEFT o RIGHT, el codigo se lee al instante.
  • Necesitas un trozo del medio o una posicion dinamica: usa SUBSTRING.
  • Necesitas recortar por un patron y no por longitud: mira hacia split_part o las expresiones regulares.

Un ejemplo realista: agrupar empleados por la primera letra de su departamento con LEFT, mucho mas limpio que SUBSTRING:

SELECT LEFT(dept, 1) AS dept_initial,
       count(*)       AS people
FROM employees
GROUP BY LEFT(dept, 1)
ORDER BY dept_initial;

MySQL y ClickHouse

Buena noticia: LEFT y RIGHT existen en MySQL con la misma sintaxis LEFT(str, len) y RIGHT(str, len), asi que las consultas se trasladan casi sin cambios.

  • MySQL no admite longitud negativa: LEFT('abc', -1) devuelve una cadena vacia, no "todo salvo el ultimo caracter". Esta es la diferencia principal al migrar.
  • ClickHouse tambien tiene left y right; un argumento negativo ahi funciona como en PostgreSQL, contando desde el final.
  • En MySQL ambas funciones cuentan caracteres segun el juego de caracteres actual de la columna, lo que suele coincidir con el comportamiento de PostgreSQL para UTF-8.
-- Works identically in PostgreSQL and MySQL
SELECT LEFT(email, 3)  AS prefix,
       RIGHT(email, 3) AS suffix
FROM users;

En resumen: LEFT y RIGHT son la forma mas rapida de tomar el borde de una cadena. Recuerda la longitud negativa como "recortar por el otro extremo", limpia siempre los separadores antes de enmascarar y ten presente que el argumento negativo no funciona en MySQL.

Practica con ejercicios reales

Resuelve ejercicios en el entrenador de SQL con corrección instantánea y pistas.

Abrir el entrenador