Tablas temporales
Una tabla temporal es una tabla que solo existe durante la sesión actual de MySQL. Se crea con CREATE TEMPORARY TABLE y se destruye automáticamente cuando la conexión se cierra. Otras sesiones no pueden ver ni acceder a tus tablas temporales, lo que las hace ideales para almacenar resultados intermedios durante cálculos complejos.
Sintaxis
CREATE TEMPORARY TABLE nombre_tabla (
columna1 tipo_de_dato,
columna2 tipo_de_dato,
...
);La sintaxis es idéntica a CREATE TABLE, con la única diferencia de la palabra TEMPORARY.
Crear una tabla temporal
CREATE TEMPORARY TABLE resumen_ventas (
categoria VARCHAR(100),
total_productos INT,
ingresos DECIMAL(12, 2)
);Query OK, 0 rows affected (0.00 sec)
La creación es instantánea porque las tablas temporales se almacenan en memoria o en archivos temporales del sistema, no en el directorio de datos permanente de MySQL.
Puedes insertar datos y consultarla como cualquier otra tabla:
INSERT INTO resumen_ventas
SELECT
c.nombre AS categoria,
COUNT(DISTINCT dp.producto_id) AS total_productos,
SUM(dp.cantidad * dp.precio_unitario) AS ingresos
FROM categorias c
JOIN productos p ON p.categoria_id = c.id
JOIN detalle_pedidos dp ON dp.producto_id = p.id
GROUP BY c.nombre;
SELECT * FROM resumen_ventas ORDER BY ingresos DESC;| categoria | total_productos | ingresos |
|---|---|---|
| Portátiles | 3 | 4948.00 |
| Smartphones | 3 | 2098.98 |
| Accesorios electrónicos | 2 | 189.95 |
| Running | 1 | 259.98 |
| Cocina | 2 | 289.98 |
| Muebles | 2 | 798.00 |
| Fitness | 3 | 269.97 |
| Programación | 2 | 149.96 |
| Novelas | 3 | 57.96 |
| Camisetas | 2 | 84.97 |
| Pantalones | 2 | 169.97 |
Crear desde un SELECT
La forma más habitual de crear tablas temporales es a partir de una consulta:
CREATE TEMPORARY TABLE clientes_vip AS
SELECT
c.id,
c.nombre,
c.apellidos,
COUNT(p.id) AS total_pedidos,
SUM(p.total) AS gasto_total
FROM clientes c
JOIN pedidos p ON c.id = p.cliente_id
GROUP BY c.id, c.nombre, c.apellidos
HAVING gasto_total > 500;Ahora puedes usar clientes_vip en consultas posteriores sin repetir la subconsulta compleja:
SELECT nombre, apellidos, total_pedidos, gasto_total
FROM clientes_vip
ORDER BY gasto_total DESC;| nombre | apellidos | total_pedidos | gasto_total |
|---|---|---|---|
| Pedro | Fernández Castro | 2 | 1979.97 |
| María | García López | 3 | 1849.95 |
| Carmen | Ruiz Jiménez | 1 | 1399.00 |
| Carlos | Rodríguez Martín | 2 | 1029.98 |
| Andrés | Vega Romero | 1 | 699.00 |
| David | Sánchez Moreno | 2 | 509.97 |
Visibilidad entre sesiones
Las tablas temporales son privadas de cada sesión. Si dos usuarios se conectan simultáneamente y ambos crean una tabla temporal con el mismo nombre, cada uno tiene su propia copia independiente:
-- Sesión 1
CREATE TEMPORARY TABLE datos (valor INT);
INSERT INTO datos VALUES (100);
-- Sesión 2 (al mismo tiempo)
CREATE TEMPORARY TABLE datos (valor INT);
INSERT INTO datos VALUES (200);
-- Cada sesión ve solo sus propios datosEsta privacidad elimina la necesidad de coordinar nombres entre sesiones o preocuparse por conflictos.
Tabla temporal con el mismo nombre que una permanente
Si creas una tabla temporal con el mismo nombre que una tabla permanente, la tabla temporal "oculta" la permanente durante tu sesión:
-- La tabla permanente 'productos' tiene 30 filas
SELECT COUNT(*) FROM productos; -- Resultado: 30
CREATE TEMPORARY TABLE productos (
id INT PRIMARY KEY,
nombre VARCHAR(100)
);
INSERT INTO productos VALUES (1, 'Producto temporal');
-- Ahora accedemos a la tabla temporal
SELECT COUNT(*) FROM productos; -- Resultado: 1
-- Al eliminar la temporal, reaparece la permanente
DROP TEMPORARY TABLE productos;
SELECT COUNT(*) FROM productos; -- Resultado: 30Aunque esta capacidad existe, no es una práctica recomendable. Usar el mismo nombre causa confusión y errores difíciles de diagnosticar. Nombra las tablas temporales con un prefijo descriptivo como tmp_ o un nombre claramente diferente.
Operaciones con tablas temporales
Las tablas temporales soportan las mismas operaciones que las permanentes: INSERT, UPDATE, DELETE, SELECT con JOINs, índices, ALTER TABLE, etc.
-- Añadir un índice para mejorar consultas
ALTER TABLE clientes_vip ADD INDEX idx_gasto (gasto_total);
-- Actualizar datos
UPDATE clientes_vip SET gasto_total = gasto_total * 1.1 WHERE total_pedidos > 2;
-- Usar en JOINs
SELECT cv.nombre, cv.gasto_total, p.id AS ultimo_pedido
FROM clientes_vip cv
JOIN pedidos p ON cv.id = p.cliente_id
WHERE p.fecha_pedido = (
SELECT MAX(fecha_pedido)
FROM pedidos
WHERE cliente_id = cv.id
);Tablas temporales y transacciones
Las tablas temporales creadas con InnoDB (el motor por defecto) participan en transacciones:
CREATE TEMPORARY TABLE temp_calculo (id INT, valor DECIMAL(10,2));
START TRANSACTION;
INSERT INTO temp_calculo VALUES (1, 100.00);
INSERT INTO temp_calculo VALUES (2, 200.00);
ROLLBACK;
SELECT * FROM temp_calculo;Empty set (0.00 sec)
El ROLLBACK deshace las inserciones, pero la tabla temporal sigue existiendo (vacía). Las operaciones DDL (CREATE TEMPORARY TABLE, DROP TEMPORARY TABLE) no se pueden deshacer con rollback.
Eliminar tablas temporales
Las tablas temporales se eliminan automáticamente al cerrar la sesión. Si necesitas eliminarla antes:
DROP TEMPORARY TABLE resumen_ventas;Usa DROP TEMPORARY TABLE en lugar de DROP TABLE. La palabra TEMPORARY es importante: garantiza que solo se elimina una tabla temporal. Si usas DROP TABLE y no existe una tabla temporal con ese nombre, MySQL eliminaría la tabla permanente (si existe), lo que podría ser catastrófico.
-- Seguro: solo elimina la tabla temporal
DROP TEMPORARY TABLE IF EXISTS datos_temp;
-- Peligroso: podría eliminar una tabla permanente
DROP TABLE IF EXISTS datos_temp;Casos de uso
El caso más común es simplificar consultas complejas. En lugar de escribir una consulta enorme con múltiples subconsultas anidadas, puedes dividirla en pasos:
-- Paso 1: Calcular métricas por empleado
CREATE TEMPORARY TABLE tmp_metricas_empleado AS
SELECT
e.id,
e.nombre,
e.apellidos,
COUNT(p.id) AS pedidos_gestionados,
COALESCE(SUM(p.total), 0) AS ingresos_generados
FROM empleados e
LEFT JOIN pedidos p ON e.id = p.empleado_id
GROUP BY e.id, e.nombre, e.apellidos;
-- Paso 2: Comparar con la media
SELECT
nombre,
apellidos,
pedidos_gestionados,
ingresos_generados,
ROUND(ingresos_generados / NULLIF(pedidos_gestionados, 0), 2) AS ticket_medio
FROM tmp_metricas_empleado
WHERE pedidos_gestionados > 0
ORDER BY ingresos_generados DESC;| nombre | apellidos | pedidos_gestionados | ingresos_generados | ticket_medio |
|---|---|---|---|---|
| Natalia | Herrera López | 10 | 6422.89 | 642.29 |
| Daniel | Vargas Martín | 8 | 3148.88 | 393.61 |
| Patricia | Cano Sánchez | 7 | 1753.88 | 250.55 |
Otro caso habitual es crear tablas temporales para reportes que requieren múltiples pasadas sobre los datos, o para almacenar parámetros de configuración durante procedimientos almacenados complejos.
Limitaciones
Las tablas temporales no pueden ser referenciadas por claves foráneas de otras tablas. No puedes referenciar la misma tabla temporal más de una vez en la misma consulta:
CREATE TEMPORARY TABLE tmp_numeros (n INT);
INSERT INTO tmp_numeros VALUES (1), (2), (3);
-- Esto falla en MySQL
SELECT a.n, b.n
FROM tmp_numeros a
JOIN tmp_numeros b ON a.n < b.n;ERROR 1137 (HY000): Can't reopen table: 'a'
La solución es crear una segunda tabla temporal con los mismos datos, o usar una CTE:
WITH numeros AS (SELECT n FROM tmp_numeros)
SELECT a.n, b.n
FROM tmp_numeros a
JOIN numeros b ON a.n < b.n;Las tablas temporales tampoco aparecen en SHOW TABLES ni en information_schema.TABLES, lo que dificulta su inspección.
Limpieza
DROP TEMPORARY TABLE IF EXISTS resumen_ventas;
DROP TEMPORARY TABLE IF EXISTS clientes_vip;
DROP TEMPORARY TABLE IF EXISTS temp_calculo;
DROP TEMPORARY TABLE IF EXISTS tmp_metricas_empleado;
DROP TEMPORARY TABLE IF EXISTS tmp_numeros;Con esto completamos la sección de definición de tablas. En la siguiente sección exploraremos las restricciones: NOT NULL, PRIMARY KEY, FOREIGN KEY, UNIQUE, DEFAULT, CHECK y AUTO_INCREMENT.
Escrito por Eduardo Lázaro
