Todo lo esencial de SQL en una sola hoja.
Consultas, comandos y operaciones clave explicadas de forma clara, ordenada y con ejemplos prácticos.
SELECT
- Joins:
INNER
|LEFT
|RIGHT
|FULL OUTER
|CROSS
|SELF
|NATURAL
- Operadores de conjunto:
UNION
/UNION ALL
|INTERSECT
|EXCEPT
/MINUS
- Subconsultas avanzadas:
ANY
/ALL
|WITH
Los comandos DDL (Data Definition Language) permiten definir, modificar y eliminar estructuras de bases de datos como esquemas, tablas y vistas.
CREATE SCHEMA nombre_esquema;
-- o (MySQL):
CREATE DATABASE nombre_base_datos;
[!NOTE] >
SCHEMA
≠DATABASE
en algunos motores (como MySQL/PostgreSQL). En PostgreSQL, el esquema es un contenedor lógico para objetos de base de datos como tablas, vistas, secuencias, etc. En MySQL, el esquema es equivalente a una base de datos.
CREATE TABLE tabla (
col1 datatype,
col2 datatype,
col3 datatype,
col4 datatype,
);
También se puede hacer:
CREATE TABLE IF NOT EXISTS tabla ( ... );
CREATE TABLE IF NO EXISTS books (
id SERIAL PRIMARY KEY,
title VARCHAR(100) NOT NULL,
author VARCHAR(100) NOT NULL
);
CREATE TABLE nombre_esquema.tabla (
col1 datatype,
col2 datatype
);
CREATE VIEW nombre_vista AS
SELECT columna1, columna2 FROM tabla;
CREATE VIEW vista_ventas AS
SELECT fecha, SUM(total) AS total_diario
FROM ventas
GROUP BY fecha;
DROP TABLE IF EXISTS tabla;
DROP VIEW IF EXISTS nombre_vista;
DROP SCHEMA IF EXISTS nombre_esquema CASCADE;
DROP DATABASE IF EXISTS nombre_base_datos;
ALTER TABLE tabla ADD nueva_columna tipo;
ALTER TABLE tabla RENAME COLUMN antigua_columna TO nueva_columna;
-- En MySQL
ALTER TABLE tabla MODIFY columna tipo;
-- En PostgreSQL
ALTER TABLE tabla ALTER COLUMN columna TYPE nuevo_tipo;
ALTER TABLE tabla DROP COLUMN columna;
Borra todas las filas de una tabla existente.
TRUNCATE TABLE tabla;
TRUNCATE TABLE tabla RESTART IDENTITY; -- PostgreSQL: reinicia IDs auto
DQL (Data Query Language) se utiliza para consultar datos de una base de datos. La palabra clave principal es SELECT
, acompañada de múltiples cláusulas opcionales que permiten filtrar, agrupar, ordenar y combinar resultados.
SELECT * FROM tabla;
SELECT col1, col2 FROM tabla;
Seleccionar / Usar una vista (view):
SELECT * FROM vista_ventas WHERE fecha = '2024-01-01';
Especificar el número de registros a devolver desde la parte superior de la tabla.
-- SQL Server
SELECT TOP 10 * FROM tabla;
SELECT TOP number columnas FROM tabla WHERE condicion;
SELECT TOP percent columnas FROM tabla WHERE condicion;
-- PostgreSQL / MySQL / SQLite
SELECT * FROM tabla LIMIT 10;
SELECT * FROM tabla LIMIT 10 OFFSET 5;
Note
No todos los sistemas de bases de datos soportan SELECT TOP
.
El equivalente en MySQL es la cláusulaLIMIT
.
Un alias es el nombre temporal que toma una tabla o columna
SELECT columna AS alias FROM tabla;
SELECT columna FROM tabla AS alias;
SELECT col1 AS alias1, col2 AS alias2;
SELECT col1 AS alias1, col2 AS alias2 FROM tabla AS alias3;
SELECT t.col1, t.col2 FROM tabla AS t;
SELECT * FROM tabla WHERE columna = valor;
SELECT col1, col2 FROM tabla WHERE condicion;
SELECT * FROM tabla WHERE NOT condicion;
SELECT * FROM tabla WHERE EXISTS (SELECT 1 FROM otra_tabla WHERE condicion);
SELECT * FROM tabla WHERE condicion1 AND condicion2;
SELECT * FROM tabla WHERE condicion1 AND condicion2 AND ...;
SELECT * FROM tabla WHERE condicion1 OR condicion2;
SELECT * FROM tabla WHERE condicion1 OR condicion2 OR ...;
SELECT * FROM tabla WHERE condicion1 AND (condicion2 OR condicion3);
SELECT * FROM tabla WHERE col1 = 'A' AND col2 > 10;
SELECT * FROM tabla WHERE col1 = 'B' OR col2 < 5;
SELECT * FROM tabla WHERE col1 = 'X' AND (col2 = 'Y' OR col3 = 'Z');
SELECT * FROM tabla WHERE columna IS NULL;
SELECT * FROM tabla WHERE columna IS NOT NULL;
SELECT col1, col2 FROM tabla WHERE columna BETWEEN value1 AND value2;
SELECT * FROM tabla WHERE columna BETWEEN 10 AND 20;
SELECT * FROM ventas WHERE fecha BETWEEN '2024-01-01' AND '2024-12-31';
SELECT * FROM tabla WHERE columna LIKE 'a%'; -- empieza por 'a'
SELECT * FROM tabla WHERE columna LIKE '%a'; -- termina por 'a'
SELECT * FROM tabla WHERE columna LIKE '%texto%'; -- contiene 'texto'
SELECT * FROM tabla WHERE columna LIKE '_r%'; -- segundo carácter es 'r'
SELECT * FROM tabla WHERE columna LIKE 'a%b'; -- empieza por 'a' y termina por 'b'
SELECT * FROM tabla WHERE columna LIKE 'a%b%c'; -- empieza por 'a', termina por 'c' y tiene 'b' en cualquier posición
%
(signo porcentaje) - carácter comodín que representa cero, uno o varios caracteres.\_
(underscore) - carácter comodín que representa un único carácter.
Esencialmente, el operador IN
es una abreviatura de las condiciones OR
múltiples.
SELECT columnas FROM tabla WHERE columna IN (value1, value2, …);
SELECT * FROM tabla WHERE columna IN ('A', 'B', 'C');
SELECT columnas FROM tabla WHERE columna IN (SELECT columna FROM otra_tabla);
SELECT * FROM tabla
WHERE EXISTS (
SELECT 1
FROM otra_tabla
WHERE condicion
);
SELECT name
FROM countries
WHERE EXISTS (
SELECT *
FROM cities
WHERE country_id = countries.id
)
SELECT * FROM tabla ORDER BY column;
SELECT * FROM tabla ORDER BY column DESC;
SELECT * FROM tabla ORDER BY col1 ASC, col2 DESC;
SELECT DISTINCT col1, col2 FROM tabla;
SELECT columna, COUNT(*) FROM tabla GROUP BY columna;
SELECT departamento, COUNT(*) FROM empleados GROUP BY departamento;
SELECT col1, COUNT(col2) FROM tabla WHERE condicion
GROUP BY col1 ORDER BY COUNT(col2) DESC;
SELECT columna, COUNT(*) FROM tabla GROUP BY columna HAVING COUNT(*) > 10;
SELECT COUNT(col1), col2 FROM tabla GROUP BY col2 HAVING COUNT(col1) > 5;
SELECT departamento, COUNT(*) FROM empleados GROUP BY departamento HAVING COUNT(*) > 10;
SELECT COUNT(*) FROM tabla;
SELECT COUNT(DISTINCT columna) FROM tabla;
SELECT SUM(total) FROM ventas;
SELECT AVG(salario) FROM empleados;
SELECT MIN(precio), MAX(precio) FROM productos;
A continuación un set de tablas de ejemplo y cómo quedan los resultados tras cada tipo de JOIN
.
empleados
id | nombre | dep_id | supervisor_id |
---|---|---|---|
1 | Juan | 1 | NULL |
2 | María | 2 | 1 |
3 | Pedro | 3 | 1 |
4 | Ana | 2 | 2 |
departamentos
id | departamento |
---|---|
1 | Marketing |
2 | Ventas |
3 | Recursos Humanos |
4 | Finanzas |
SELECT columnas
FROM tabla1
INNER JOIN tabla2
ON tabla1.columna = tabla2.columna;
SELECT tabla1.columna1, tabla2.columna2, tabla3.columna3
FROM ( ( tabla1
INNER JOIN tabla2
ON relacion
)
INNER JOIN tabla3
ON relacion
);
SELECT e.nombre, d.departamento
FROM empleados e
INNER JOIN departamentos d
ON e.dep_id = d.id;
Resultado:
nombre | departamento |
---|---|
Juan | Marketing |
María | Ventas |
Pedro | Recursos Humanos |
Ana | Ventas |
SELECT e.nombre, d.departamento
FROM empleados e
LEFT JOIN departamentos d
ON e.dep_id = d.id;
Resultado:
nombre | departamento |
---|---|
Juan | Marketing |
María | Ventas |
Pedro | Recursos Humanos |
Ana | Ventas |
SELECT columnas
FROM tabla1
RIGHT JOIN tabla2
ON tabla1.columna = tabla2.columna;
SELECT e.nombre, d.departamento
FROM empleados e
RIGHT JOIN departamentos d
ON e.dep_id = d.id;
Resultado:
nombre | departamento |
---|---|
Juan | Marketing |
María | Ventas |
Pedro | Recursos Humanos |
Ana | Ventas |
NULL | Finanzas |
SELECT columnas
FROM tabla1
FULL OUTER JOIN tabla2
ON tabla1.columna = tabla2.columna;
SELECT e.nombre, d.departamento
FROM empleados e
FULL OUTER JOIN departamentos d
ON e.dep_id = d.id;
Resultado:
nombre | departamento |
---|---|
Juan | Marketing |
María | Ventas |
Pedro | Recursos Humanos |
Ana | Ventas |
NULL | Finanzas |
SELECT e.nombre, d.departamento
FROM empleados e
CROSS JOIN departamentos d;
Resultado (4×4 = 16 filas): Ejemplo de las primeras 4 filas:
nombre | departamento |
---|---|
Juan | Marketing |
Juan | Ventas |
Juan | Recursos Humanos |
Juan | Finanzas |
SELECT e.nombre AS empleado,
s.nombre AS supervisor
FROM empleados e
JOIN empleados s
ON e.supervisor_id = s.id;
Resultado:
empleado | supervisor |
---|---|
María | Juan |
Pedro | Juan |
Ana | María |
Une automáticamente por columnas de mismo nombre (
dep\_id = id
). Puede ser inseguro si hay nombres duplicados.
SELECT *
FROM empleados
NATURAL JOIN departamentos;
Resultado equivalente a INNER JOIN:
id | nombre | departamento |
---|---|---|
1 | Juan | Marketing |
2 | María | Ventas |
3 | Pedro | Recursos Humanos |
4 | Ana | Ventas |
Combina los resultados de dos o más consultas SELECT
en un solo conjunto de resultados.
- Cada sentencia
SELECT
debe tener el mismo número de columnas. - Las columnas deben tener el mismo tipo de datos.
- Las columnas en cada
SELECT
deben también estar en el mismo orden.
SELECT columnas FROM tabla1
UNION
SELECT columna FROM tabla2;
El operador UNION
solo selecciona valores distintos, UNION ALL
permitirá duplicados
SELECT columnas FROM tabla1
UNION ALL
SELECT columnas FROM tabla3;
Ejemplo: "Obtener los nombres de ciclistas y nadadores españoles".
SELECT name FROM cycling WHERE country = 'ES'
UNION
SELECT name FROM swimming WHERE country = 'ES';
Devuelve los registros que están presentes en ambas tablas. Suele utilizarse del mismo modo que UNION
.
SELECT columnas FROM tabla1
INTERSECT
SELECT columna FROM tabla2;
Ejemplo: "Obtener los nombres de ciclistas que también hacen triatlón en España".
SELECT name FROM cycling WHERE country = 'ES'
INTERSECT
SELECT name FROM triathlon WHERE country = 'ES';
Utilizado para devolver todos los registros de la primera sentencia SELECT
que no se encuentran en la segunda sentencia SELECT
. Generalmente se utiliza de la misma manera que UNION.
SELECT columnas FROM tabla1
EXCEPT
SELECT columna FROM tabla2;
Ejemplo: "Obtener los nombres de ciclistas que no hacen triatlón en España".
SELECT name FROM cycling WHERE country = 'ES'
EXCEPT
SELECT name FROM triathlon WHERE country = 'ES';
ANY
- Devuelve verdadero si algún valor de la subconsulta cumple la condicion.ALL
- Devuelve verdadero si todos los valores de la subconsulta cumplen la condicion.
SELECT * FROM tabla WHERE columna operator ANY (SELECT * FROM tabla WHERE condicion);
SELECT * FROM tabla WHERE columna operator ALL (SELECT * FROM tabla WHERE condicion);
SELECT * FROM productos
WHERE precio > ANY (
SELECT precio FROM productos WHERE categoria = 'A'
);
SELECT * FROM productos
WHERE precio > ALL (
SELECT precio FROM productos WHERE categoria = 'B'
);
ANY
- Busca todos los productos cuyo precio sea mayor que al menos uno de los precios de la categoría A (> mínimo
de los valores).ALL
- Busca todos los productos cuyo precio sea mayor que todos los precios de la categoría B (> máximo
de los valores).
Subconsultas con alias temporales
WITH alias AS (
SELECT * FROM tabla WHERE condicion
)
SELECT * FROM alias WHERE condicion;
WITH empleados_activos AS (
SELECT * FROM empleados WHERE activo = TRUE
)
SELECT * FROM empleados_activos WHERE salario > 3000;
Insertar una fila en todas las columnas:
INSERT INTO tabla VALUES (value1, value2 …);
INSERT INTO empleados VALUES (2, 'Rocío', 1, NULL);
Insertar múltiples filas:
INSERT INTO tabla (col1, col2) VALUES
(value1, value2),
(value3, value4),
(value5, value6);
INSERT INTO empleados (id, nombre, dep_id) VALUES
(2, 'Rocío', 1),
(3, 'Elena', 2),
(4, 'Ángel', 3);
Insertar desde otra tabla:
INSERT INTO tabla (col1, col2)
SELECT col1, col2
FROM otra_tabla;
INSERT INTO empleados_ventas (id, nombre)
SELECT id, nombre
FROM empleados WHERE dep_id = 2;
Actualizar columnas con condición:
UPDATE tabla
SET col1 = value1, col2 = value2
WHERE condicion;
UPDATE empleados
SET salario = salario * 1.1
WHERE dep_id = 1;
-- UPDATE con JOIN (PostgreSQL)
UPDATE empleados e
SET salario = s.nuevo_salario
FROM ajustes s
WHERE e.id = s.emp_id;
Eliminar filas según condición:
DELETE FROM tabla WHERE condicion;
DELETE FROM empleados WHERE id = 7;
Eliminar todas las filas de una tabla (mantiene la estructura):
DELETE FROM empleados;
Llamar a un procedimiento almacenado:
CALL procedimiento(param1, param2);
CALL sumar_sueldos(3);
Bloquear una tabla para lectura/escritura (evitar modificaciones):
LOCK TABLES tabla1 READ, tabla2 WRITE;
LOCK TABLES empleados WRITE;
UNLOCK TABLES;
[!NOTE] > No disponible en BigQuery (gestión de permisos a través de consola IAM y control a nivel dataset).
-- Conceder SELECT y INSERT a un usuario
GRANT SELECT, INSERT ON empleados TO juan;
-- Conceder todos los privilegios con opción de re-grant
GRANT ALL PRIVILEGES ON base_datos.* TO 'app_user'@'%'
WITH GRANT OPTION;
[!NOTE] > No disponible en BigQuery (gestión de permisos a través de consola IAM y control a nivel dataset).
-- Revocar permisos
REVOKE INSERT ON empleados FROM juan;
[!NOTE] > No disponible en BigQuery (gestión de permisos a través de consola IAM y control a nivel dataset).
TCL (Transaction Control Language) gestiona el control de las transacciones, asegurando la integridad de los datos. Incluye comandos para confirmar, deshacer y establecer puntos intermedios.
-- SQL Server / Oracle
BEGIN TRANSACTION;
-- MySQL / PostgreSQL (implícito tras cualquier DML)
START TRANSACTION;
COMMIT;
Guarda permanentemente todas las operaciones realizadas desde el inicio de la transacción.
ROLLBACK;
Cancela toda la transacción, dejando la base de datos en el estado previo.
SAVEPOINT nombre_punto;
ROLLBACK TO SAVEPOINT
- Deshacer hasta un punto
SAVEPOINT nombre_punto;
-- .. operaciones intermedias ...
ROLLBACK TO SAVEPOINT nombre_punto;
Permite deshacer hasta un punto específico sin abordar toda la transacción.
RELEASE SAVEPOINT
- Eliminar un punto intermedio
SAVEPOINT nombre_punto;
-- .. operaciones intermedias ...
ROLLBACK TO SAVEPOINT nombre_punto;
RELEASE SAVEPOINT nombre_punto;
-- Definir nivel de aislamiento (PostgreSQL, MySQL 8+)
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- Modo de solo lectura
SET TRANSACTION READ ONLY;
Controla concurrencia y visibilidad de datos entre transacciones.