Una de las mejores cosas de SQL es que con un puñado de comandos bien aprendidos puedes resolver el 90% de los problemas del día a día. No necesitas memorizar cientos de funciones ni ser un experto en administración de bases de datos para ser productivo.
En este artículo tienes una guía de referencia completa con los comandos SQL esenciales, explicados de forma clara y con ejemplos reales que puedes copiar, pegar y adaptar inmediatamente. Guárdalo en favoritos: lo vas a consultar más de una vez. 🔖
Usaremos como base de datos de ejemplo una tienda online con estas tablas: clientes, productos y pedidos. Así todos los ejemplos tienen contexto real y no parecen sacados de la nada.
Los dos tipos de comandos SQL que debes conocer
Antes de entrar en los comandos, vale la pena saber que SQL los organiza en dos grandes categorías:
- 🏗️ DDL (Data Definition Language) — Comandos que definen y modifican la estructura de la base de datos: crear tablas, modificarlas, eliminarlas. Son:
CREATE,ALTER,DROP,TRUNCATE. - ✏️ DML (Data Manipulation Language) — Comandos que trabajan con los datos dentro de las tablas: consultar, insertar, actualizar, eliminar. Son:
SELECT,INSERT,UPDATE,DELETE.
En el día a día como principiante, usarás mucho más DML que DDL. Pero los dos son importantes y los vamos a ver.
📋 Comandos DDL: definir la estructura
CREATE DATABASE — crear una base de datos
CREATE DATABASE tienda_online;El primer paso de cualquier proyecto: crear el contenedor donde van a vivir todas tus tablas.
-- Seleccionar la base de datos para trabajar con ella
USE tienda_online;CREATE TABLE — crear una tabla
CREATE TABLE clientes (
id INT PRIMARY KEY AUTO_INCREMENT,
nombre VARCHAR(100) NOT NULL,
email VARCHAR(150) UNIQUE NOT NULL,
ciudad VARCHAR(80),
creado_en DATETIME DEFAULT CURRENT_TIMESTAMP
);Los tipos de datos más usados en columnas:
| Tipo | Para qué sirve | Ejemplo |
|---|---|---|
INT | Números enteros | edad, stock, cantidad |
DECIMAL(n,d) | Números con decimales | precio, salario |
VARCHAR(n) | Texto de longitud variable | nombre, email, ciudad |
TEXT | Texto largo sin límite fijo | descripción, comentarios |
DATE | Solo fecha | fecha_nacimiento |
DATETIME | Fecha y hora | creado_en, actualizado_en |
BOOLEAN | Verdadero o falso | activo, verificado |
ENUM | Lista de valores permitidos | estado ('activo','inactivo') |
ALTER TABLE — modificar una tabla existente
-- Agregar una columna nueva
ALTER TABLE clientes ADD COLUMN telefono VARCHAR(20);
-- Modificar el tipo de una columna existente
ALTER TABLE clientes MODIFY COLUMN telefono VARCHAR(30);
-- Eliminar una columna
ALTER TABLE clientes DROP COLUMN telefono;
-- Renombrar una columna
ALTER TABLE clientes RENAME COLUMN ciudad TO localidad;ALTER TABLE es el comando que usas cuando la estructura de tu tabla necesita cambiar sin perder los datos que ya tiene. Muy útil cuando evolucionan los requerimientos de un proyecto.
DROP TABLE — eliminar una tabla
DROP TABLE clientes;⚠️ Cuidado: DROP TABLE elimina la tabla y todos sus datos de forma permanente e irreversible. No hay papelera de reciclaje en SQL.
TRUNCATE TABLE — vaciar una tabla sin eliminarla
TRUNCATE TABLE clientes;La diferencia con DROP: TRUNCATE borra todos los registros pero mantiene la estructura de la tabla intacta. Ideal para limpiar datos de prueba antes de cargar datos reales.
✏️ Comandos DML: trabajar con los datos
INSERT INTO — insertar datos
Agrega nuevas filas a una tabla.
-- Insertar un solo registro
INSERT INTO clientes (nombre, email, ciudad)
VALUES ('Ana García', 'ana@email.com', 'Ciudad de México');
-- Insertar varios registros de una sola vez
INSERT INTO clientes (nombre, email, ciudad) VALUES
('Luis Pérez', 'luis@email.com', 'Bogotá'),
('María López', 'maria@email.com', 'Lima'),
('Carlos Ruiz', 'carlos@email.com','Buenos Aires');💡 Tip: Siempre nombra las columnas explícitamente aunque vayas a llenarlas todas. Si en el futuro agregas una columna nueva a la tabla, tu INSERT seguirá funcionando sin cambios.
🔍 SELECT — el comando más importante de SQL
SELECT es el corazón de SQL. Con él consultas, filtras, ordenas, agrupas y transformas datos. Merece su propia sección extendida porque tiene muchas variantes que necesitas dominar.
SELECT básico
-- Todas las columnas de todos los registros
SELECT * FROM clientes;
-- Columnas específicas
SELECT nombre, email FROM clientes;
-- Con alias para las columnas (renombrar en el resultado)
SELECT nombre AS cliente, email AS correo FROM clientes;WHERE — filtrar resultados
-- Igual a
SELECT * FROM clientes WHERE ciudad = 'Bogotá';
-- Diferente de
SELECT * FROM productos WHERE stock != 0;
-- Mayor que / Menor que
SELECT * FROM productos WHERE precio > 50;
SELECT * FROM productos WHERE precio <= 100;
-- Varias condiciones con AND
SELECT * FROM productos WHERE precio > 50 AND stock > 20;
-- Varias condiciones con OR
SELECT * FROM clientes
WHERE ciudad = 'Lima' OR ciudad = 'Bogotá';
-- Negar una condición con NOT
SELECT * FROM clientes WHERE NOT ciudad = 'Lima';BETWEEN — rango de valores
-- Productos con precio entre 20 y 100 (inclusive)
SELECT nombre, precio FROM productos
WHERE precio BETWEEN 20 AND 100;
-- También funciona con fechas
SELECT * FROM pedidos
WHERE fecha BETWEEN '2026-01-01' AND '2026-06-30';LIKE — buscar por patrón de texto
-- Nombres que empiezan con "A"
SELECT * FROM clientes WHERE nombre LIKE 'A%';
-- Emails que terminan en "@gmail.com"
SELECT * FROM clientes WHERE email LIKE '%@gmail.com';
-- Nombres que contienen "ar" en cualquier posición
SELECT * FROM clientes WHERE nombre LIKE '%ar%';
-- Exactamente 4 caracteres
SELECT * FROM productos WHERE nombre LIKE '____';El símbolo % representa cualquier cantidad de caracteres (incluyendo ninguno). El símbolo _ representa exactamente un carácter.
IN — comparar con una lista de valores
-- Clientes de estas ciudades específicas
SELECT * FROM clientes
WHERE ciudad IN ('Lima', 'Bogotá', 'Santiago');
-- Equivalente a usar OR tres veces, pero mucho más limpio
-- Productos con id 1, 3 o 5
SELECT * FROM productos WHERE id IN (1, 3, 5);IS NULL / IS NOT NULL — valores vacíos
-- Clientes sin teléfono registrado
SELECT nombre, email FROM clientes WHERE telefono IS NULL;
-- Clientes que sí tienen teléfono
SELECT nombre, telefono FROM clientes WHERE telefono IS NOT NULL;⚠️ Importante: Nunca uses = NULL para buscar valores nulos. Eso no funciona en SQL. Siempre usa IS NULL o IS NOT NULL.
ORDER BY — ordenar resultados
-- De menor a mayor precio (ascendente por defecto)
SELECT nombre, precio FROM productos ORDER BY precio ASC;
-- De mayor a menor precio
SELECT nombre, precio FROM productos ORDER BY precio DESC;
-- Ordenar por múltiples columnas
SELECT nombre, ciudad FROM clientes
ORDER BY ciudad ASC, nombre ASC;LIMIT — limitar el número de resultados
-- Los 5 productos más caros
SELECT nombre, precio FROM productos
ORDER BY precio DESC
LIMIT 5;
-- Paginación: saltarse los primeros 10 y traer los siguientes 10
SELECT * FROM productos
LIMIT 10 OFFSET 10;LIMIT con OFFSET es la base de la paginación en aplicaciones web. La página 1 sería LIMIT 10 OFFSET 0, la página 2 sería LIMIT 10 OFFSET 10, y así.
DISTINCT — eliminar duplicados
-- Ver todas las ciudades donde tenemos clientes (sin repetir)
SELECT DISTINCT ciudad FROM clientes ORDER BY ciudad;✏️ UPDATE — actualizar datos existentes
-- Actualizar un campo específico
UPDATE productos SET precio = 899.99 WHERE id = 1;
-- Actualizar varios campos a la vez
UPDATE clientes
SET ciudad = 'Monterrey', telefono = '555-9999'
WHERE id = 3;
-- Actualizar con una operación matemática
UPDATE productos SET stock = stock - 5 WHERE id = 2;⚠️ Regla de oro: Siempre usa WHERE con UPDATE. Sin él, actualizas todos los registros de la tabla. Antes de ejecutar un UPDATE importante, haz primero un SELECT con el mismo WHERE para confirmar qué registros vas a modificar.
🗑️ DELETE — eliminar registros
-- Eliminar un registro específico
DELETE FROM clientes WHERE id = 5;
-- Eliminar con condición
DELETE FROM pedidos WHERE estado = 'cancelado';
-- Eliminar registros más antiguos de cierta fecha
DELETE FROM pedidos WHERE fecha < '2025-01-01';⚠️ La misma advertencia que con UPDATE: sin WHERE, borras todo. Y en SQL no hay deshacer.
🔗 JOIN — cruzar datos de varias tablas
Los JOINs son donde SQL se vuelve verdaderamente poderoso. Te permiten combinar información de dos o más tablas en una sola consulta.
INNER JOIN — solo los registros que coinciden en ambas tablas
SELECT
clientes.nombre AS cliente,
pedidos.id AS pedido,
pedidos.total,
pedidos.estado
FROM pedidos
INNER JOIN clientes ON pedidos.cliente_id = clientes.id;Solo devuelve pedidos que tienen un cliente válido, y clientes que tienen al menos un pedido.
LEFT JOIN — todos los registros de la tabla izquierda
-- Todos los clientes, tengan pedidos o no
SELECT
clientes.nombre,
COUNT(pedidos.id) AS total_pedidos
FROM clientes
LEFT JOIN pedidos ON clientes.id = pedidos.cliente_id
GROUP BY clientes.id, clientes.nombre;Los clientes sin pedidos aparecen con NULL en las columnas de pedidos. Ideal para encontrar clientes inactivos.
RIGHT JOIN — todos los registros de la tabla derecha
-- Todos los pedidos, aunque el cliente haya sido eliminado
SELECT pedidos.id, clientes.nombre
FROM pedidos
RIGHT JOIN clientes ON pedidos.cliente_id = clientes.id;JOIN con múltiples tablas
-- Ver qué compró cada cliente, con nombre de producto
SELECT
clientes.nombre AS cliente,
productos.nombre AS producto,
detalle_pedidos.cantidad,
detalle_pedidos.precio_unit
FROM detalle_pedidos
INNER JOIN pedidos ON detalle_pedidos.pedido_id = pedidos.id
INNER JOIN clientes ON pedidos.cliente_id = clientes.id
INNER JOIN productos ON detalle_pedidos.producto_id = productos.id
ORDER BY clientes.nombre;📊 Funciones de agregación y GROUP BY
Las funciones de agregación calculan un resultado a partir de un conjunto de filas. Siempre las usarás junto con GROUP BY cuando quieras agrupar los cálculos por categoría.
Las 5 funciones esenciales
-- Contar registros
SELECT COUNT(*) AS total_clientes FROM clientes;
SELECT COUNT(telefono) AS clientes_con_telefono FROM clientes; -- ignora NULLs
-- Sumar valores
SELECT SUM(total) AS ingresos_totales FROM pedidos;
-- Promedio
SELECT AVG(precio) AS precio_promedio FROM productos;
-- Valor máximo y mínimo
SELECT MAX(precio) AS producto_mas_caro FROM productos;
SELECT MIN(precio) AS producto_mas_barato FROM productos;GROUP BY — agrupar resultados
-- Total de ventas por estado de pedido
SELECT estado, COUNT(*) AS cantidad, SUM(total) AS total_ventas
FROM pedidos
GROUP BY estado;
-- Clientes por ciudad
SELECT ciudad, COUNT(*) AS total
FROM clientes
GROUP BY ciudad
ORDER BY total DESC;HAVING — filtrar grupos (como WHERE pero para grupos)
-- Solo ciudades con más de 2 clientes
SELECT ciudad, COUNT(*) AS total
FROM clientes
GROUP BY ciudad
HAVING COUNT(*) > 2;
-- Productos con ventas totales mayores a 500
SELECT productos.nombre, SUM(detalle_pedidos.cantidad) AS unidades
FROM detalle_pedidos
INNER JOIN productos ON detalle_pedidos.producto_id = productos.id
GROUP BY productos.id, productos.nombre
HAVING SUM(detalle_pedidos.cantidad) > 5;La diferencia clave: WHERE filtra filas individuales antes de agrupar. HAVING filtra grupos después de agrupar. No son intercambiables.
🔤 Funciones de texto útiles
-- Convertir a mayúsculas / minúsculas
SELECT UPPER(nombre) FROM clientes;
SELECT LOWER(email) FROM clientes;
-- Longitud de un texto
SELECT nombre, LENGTH(nombre) AS caracteres FROM clientes;
-- Extraer parte de un texto
SELECT SUBSTRING(email, 1, 5) AS primeras_letras FROM clientes;
-- Concatenar texto
SELECT CONCAT(nombre, ' — ', ciudad) AS info FROM clientes;
-- Eliminar espacios en blanco al inicio y al final
SELECT TRIM(' hola mundo ');
-- Reemplazar texto
SELECT REPLACE(email, '@gmail.com', '@nuevo.com') FROM clientes;🔢 Funciones de fecha
-- Fecha y hora actual
SELECT NOW(); -- fecha y hora: 2026-03-29 14:35:00
SELECT CURDATE(); -- solo fecha: 2026-03-29
SELECT CURTIME(); -- solo hora: 14:35:00
-- Extraer partes de una fecha
SELECT YEAR(creado_en), MONTH(creado_en), DAY(creado_en)
FROM clientes;
-- Diferencia entre fechas en días
SELECT DATEDIFF(NOW(), creado_en) AS dias_desde_registro
FROM clientes;
-- Pedidos del mes actual
SELECT * FROM pedidos
WHERE MONTH(fecha) = MONTH(NOW())
AND YEAR(fecha) = YEAR(NOW());💡 Otros comandos y cláusulas esenciales
CASE — condicionales dentro de una consulta
SELECT
nombre,
precio,
CASE
WHEN precio < 30 THEN 'Económico'
WHEN precio < 100 THEN 'Precio medio'
ELSE 'Premium'
END AS categoria_precio
FROM productos
ORDER BY precio;COALESCE — manejar valores NULL
-- Si el teléfono es NULL, muestra "Sin teléfono"
SELECT nombre, COALESCE(telefono, 'Sin teléfono') AS telefono
FROM clientes;Subconsultas — consultas dentro de consultas
-- Clientes que han hecho al menos un pedido
SELECT nombre FROM clientes
WHERE id IN (SELECT DISTINCT cliente_id FROM pedidos);
-- Productos con precio mayor al promedio
SELECT nombre, precio FROM productos
WHERE precio > (SELECT AVG(precio) FROM productos);📌 Hoja de referencia rápida
| Comando | ¿Para qué sirve? |
|---|---|
CREATE DATABASE | Crear una base de datos |
USE | Seleccionar la base de datos activa |
CREATE TABLE | Crear una tabla nueva |
ALTER TABLE | Modificar la estructura de una tabla |
DROP TABLE | Eliminar una tabla y sus datos |
TRUNCATE TABLE | Vaciar una tabla sin eliminarla |
INSERT INTO | Insertar nuevos registros |
SELECT | Consultar datos |
WHERE | Filtrar filas |
ORDER BY | Ordenar resultados |
LIMIT | Limitar número de resultados |
DISTINCT | Eliminar duplicados |
LIKE | Buscar por patrón de texto |
BETWEEN | Filtrar por rango de valores |
IN | Comparar con lista de valores |
IS NULL | Verificar valores vacíos |
UPDATE | Modificar registros existentes |
DELETE | Eliminar registros |
INNER JOIN | Cruzar tablas (solo coincidencias) |
LEFT JOIN | Cruzar tablas (todos los de la izquierda) |
GROUP BY | Agrupar resultados |
HAVING | Filtrar grupos |
COUNT / SUM / AVG / MAX / MIN | Funciones de agregación |
CASE | Condicionales dentro de consultas |
COALESCE | Reemplazar valores NULL |
Resumen: lo que aprendiste hoy
- ✅ DDL define la estructura:
CREATE,ALTER,DROP,TRUNCATE - ✅ DML trabaja con los datos:
SELECT,INSERT,UPDATE,DELETE - ✅
WHERE,LIKE,BETWEEN,INeIS NULLson tus herramientas de filtrado - ✅
ORDER BY,LIMITyDISTINCTcontrolan cómo se presentan los resultados - ✅ Los JOINs combinan datos de varias tablas en una sola consulta
- ✅
GROUP BYyHAVINGpermiten calcular estadísticas por grupos - ✅
CASEyCOALESCEañaden lógica condicional a tus consultas - ✅ Nunca uses
UPDATEoDELETEsinWHEREen producción
🧪 ¿Cuántos de estos comandos ya dominas? Ponlos a prueba
Esta guía es una referencia, pero la única forma de saber si realmente los tienes interiorizados es enfrentarte a preguntas concretas sin mirar la respuesta.
Tenemos un test de SQL Basics con preguntas cortas y directas sobre los comandos que viste hoy. Sin límite de tiempo, sin trampa y con feedback inmediato. En pocos minutos sabrás exactamente qué tienes sólido y qué vale la pena repasar.
¿Cuál de estos comandos te resulta más complicado? ¿Los JOINs, el HAVING o algo más? Déjanos tu pregunta en los comentarios 👇 — respondemos todos.
No hay comentarios todavía. Sé el primero en compartir tu opinión.