SUBSTRING devuelve parte de una cadena, empezando en la posición que le indiques y tomando tantos caracteres como le pidas. Así es como SQL extrae un prefijo, un código o el dominio de un email de una columna de texto. Los ejemplos funcionan en PostgreSQL, MySQL, SQLite y SQL Server.
Cómo usar SUBSTRING
Pásale a SUBSTRING una cadena, la posición donde empezar (el primer carácter es 1) y cuántos caracteres tomar. Si omites la longitud, toma todo hasta el final:
SUBSTRING(string, start, length)
SELECT SUBSTRING('Joe Bloggs', 1, 3);
-- Output: Joe
-- No length: the rest of the string (SQL Server needs all three arguments)
SELECT SUBSTRING('Joe Bloggs', 5);
-- Output: Bloggs
En una consulta real, la cadena suele ser una columna. Los números de pedido como ORD-2024-001 guardan el año en los caracteres 5 a 8:
-- Input: orders
-- order_number
-- ------------
-- ORD-2024-001
-- ORD-2025-014
-- ORD-2026-102
SELECT order_number, SUBSTRING(order_number, 5, 4) AS year
FROM orders;
-- Output:
-- order_number | year
-- -------------+-----
-- ORD-2024-001 | 2024
-- ORD-2025-014 | 2025
-- ORD-2026-102 | 2026
Reglas que debes conocer
- Las posiciones empiezan en 1, no en 0. Un inicio negativo cuenta hacia atrás desde el final de la cadena, pero solo en MySQL y SQLite:
SELECT SUBSTRING('Joe Bloggs', -6, 6);
-- Output: Bloggs
-- PostgreSQL and SQL Server return '' (an empty string) instead
- Pasarte del final no es un error. Obtienes los caracteres que existan, o una cadena vacía si el inicio está después del final:
SELECT SUBSTRING('Bob', 1, 10);
-- Output: Bob
SELECT SUBSTRING('Hello', 10, 5);
-- Output: '' (an empty string)
- Si entra NULL, sale NULL. Envuelve la llamada en COALESCE cuando necesites un valor:
SELECT SUBSTRING(NULL, 1, 5);
-- Output: NULL
-- SQL Server rejects a bare NULL here, but a NULL column gives NULL
-
Filtra por prefijo con LIKE, no con SUBSTRING.
WHERE SUBSTRING(product_code, 1, 3) = 'ELE'devuelve las mismas filas queWHERE product_code LIKE 'ELE%', pero solo la versión con LIKE puede usar un índice sobreproduct_code.
Sintaxis alternativa
También verás SUBSTR, otro nombre de SUBSTRING, y LEFT y RIGHT, que toman caracteres de uno u otro extremo:
-- Not in SQL Server
SELECT SUBSTR('Joe Bloggs', 1, 3);
-- Output: Joe
-- Not in SQLite: use SUBSTRING('Joe Bloggs', 1, 3) and SUBSTRING('Joe Bloggs', -6)
SELECT LEFT('Joe Bloggs', 3);
-- Output: Joe
SELECT RIGHT('Joe Bloggs', 6);
-- Output: Bloggs
-- PostgreSQL and MySQL: the standard SQL form
SELECT SUBSTRING('Joe Bloggs' FROM 1 FOR 3);
-- Output: Joe
Para empezar después de un carácter específico, primero busca su posición:
SELECT INSTR('joe@example.com', '@');
-- Output: 4
-- PostgreSQL: POSITION('@' IN 'joe@example.com'); SQL Server: CHARINDEX('@', 'joe@example.com')
¿Cuándo deberías usar SUBSTRING?
Usa SUBSTRING cuando la parte de la cadena que necesitas está en una posición conocida, o justo después de un carácter que puedes encontrar. La mayoría de los usos entran en uno de estos cuatro casos.
Tomar los primeros caracteres
Los códigos y nombres suelen tener significado al inicio: la categoría en un código de producto, una inicial, una vista previa corta de una descripción larga. SUBSTRING(column, 1, n) toma los primeros n caracteres.
Extraer campos de valores con formato fijo
Cuando todos los valores tienen la misma estructura, cada parte está en la misma posición en cada fila: la lada en un teléfono como (303) 555-0147, el año en ORD-2024-001, o los campos de un registro de ancho fijo de un sistema antiguo.
Extraer texto después de un delimitador
Los dominios de email, las extensiones de archivo y las rutas de URL empiezan después de un carácter cuya posición cambia de fila en fila. Encuentra su posición con INSTR, empieza un carácter después y toma el resto de la cadena.
Conservar los últimos caracteres
Enmascarar un número de tarjeta o de cuenta, o leer un sufijo, implica contar hacia atrás desde el final. Calcula el inicio a partir de la longitud de la cadena o, en MySQL y SQLite, usa un inicio negativo.
Ejemplos reales de SUBSTRING
Contar productos por la categoría de su código
Los códigos de producto empiezan con una categoría de tres letras. Agrupa por ese prefijo para contar los productos de cada una:
-- Input: products
-- product_code | name
-- -------------+-----------
-- ELE-1234 | USB-C Hub
-- FUR-0087 | Desk Chair
-- ELE-5521 | Webcam
-- OFF-2210 | Stapler
SELECT SUBSTRING(product_code, 1, 3) AS category, COUNT(*) AS products
FROM products
GROUP BY SUBSTRING(product_code, 1, 3)
ORDER BY category;
-- Output:
-- category | products
-- ---------+---------
-- ELE | 2
-- FUR | 1
-- OFF | 1
Analizar un registro de ancho fijo
Las exportaciones de sistemas antiguos suelen meter los campos en posiciones fijas sin delimitador. Aquí el nombre ocupa 8 caracteres (rellenos con espacios, que TRIM elimina), la fecha de nacimiento los siguientes 8 y el código de ciudad los últimos 3:
-- Input: legacy_data
-- record
-- -------------------
-- JOHNDOE 19850315NYC
-- MARYLEE 19780912CHI
-- JANEROE 19900722LAX
SELECT
TRIM(SUBSTRING(record, 1, 8)) AS name,
SUBSTRING(record, 9, 8) AS birth_date,
SUBSTRING(record, 17, 3) AS city_code
FROM legacy_data;
-- Output:
-- name | birth_date | city_code
-- --------+------------+----------
-- JOHNDOE | 19850315 | NYC
-- MARYLEE | 19780912 | CHI
-- JANEROE | 19900722 | LAX
Obtener la extensión de cada archivo
Encuentra el punto y luego toma todo lo que viene después. La cláusula WHERE omite los archivos que no lo tienen:
-- Input: documents
-- filename
-- ---------------
-- q3-report.pdf
-- budget.xlsx
-- README
-- team-photo.jpeg
SELECT
filename,
SUBSTRING(filename, INSTR(filename, '.') + 1) AS extension
FROM documents
WHERE INSTR(filename, '.') > 0;
-- Output:
-- filename | extension
-- ----------------+----------
-- q3-report.pdf | pdf
-- budget.xlsx | xlsx
-- team-photo.jpeg | jpeg
En PostgreSQL, usa POSITION('.' IN filename) en lugar de INSTR. En SQL Server, usa CHARINDEX('.', filename) y agrega una longitud, como LEN(filename).
Enmascarar un número de tarjeta
No todos los números de tarjeta tienen 16 dígitos, así que una posición de inicio fija corta los números de American Express. Mejor cuenta hacia atrás desde el final:
-- Input: payments
-- customer_name | card_number
-- --------------+-----------------
-- Lena Fischer | 4111111111111111
-- Marcus Reid | 5500005555555559
-- Aiko Tanaka | 378282246310005
-- Wrong: position 13 only works for 16-digit cards
SELECT customer_name, '**** ' || SUBSTRING(card_number, 13, 4) AS masked_card
FROM payments;
-- Output:
-- customer_name | masked_card
-- --------------+------------
-- Lena Fischer | **** 1111
-- Marcus Reid | **** 5559
-- Aiko Tanaka | **** 005
-- Right: start 4 characters from the end
SELECT customer_name, '**** ' || SUBSTRING(card_number, LENGTH(card_number) - 3, 4) AS masked_card
FROM payments;
-- Output:
-- customer_name | masked_card
-- --------------+------------
-- Lena Fischer | **** 1111
-- Marcus Reid | **** 5559
-- Aiko Tanaka | **** 0005
En MySQL y SQL Server, une las cadenas con CONCAT() en lugar de ||. SQL Server también necesita LEN() en lugar de LENGTH().
Más lecturas sobre SUBSTRING
En este blog:
- Guía de LIKE en SQL: encuentra texto que empieza, termina o contiene un patrón
- Guía de COALESCE en SQL: reemplaza los NULL que SUBSTRING deja pasar
- Guía de GROUP BY en SQL: agrupa y cuenta filas según un valor que extrajiste
- Guía de formato de fechas en SQL: da formato a fechas y extrae sus partes sin recortar cadenas
Documentación oficial:
Beekeeper Studio es un cliente de bases de datos gratuito y de código abierto
La mejor herramienta de consultas y edición de SQL que he usado. Tiene todo lo que necesito para administrar mi base de datos. - ⭐⭐⭐⭐⭐ Mit
Beekeeper Studio es rápido, intuitivo y fácil de usar. Es compatible con muchísimas bases de datos y funciona de maravilla en Windows, Mac y Linux.
Lo que dicen los usuarios de Beekeeper Studio
"Beekeeper Studio reemplazó por completo mi antiguo flujo de trabajo con SQL. Es rápido, intuitivo y hace que trabajar con bases de datos vuelva a ser agradable."
"He probado muchas GUI de bases de datos, pero Beekeeper logra el equilibrio perfecto entre funciones y simplicidad. Simplemente funciona."