DELETE
La sentencia DELETE elimina filas de una tabla. Al igual que UPDATE, sin una cláusula WHERE que filtre las filas, DELETE elimina todas las filas de la tabla. A diferencia de TRUNCATE (que veremos más adelante), DELETE permite filtrar qué filas eliminar y es una operación que se puede deshacer dentro de una transacción.
Sintaxis
DELETE FROM tabla
WHERE condicion;La cláusula WHERE determina qué filas se eliminan. Sin WHERE, se eliminan todas.
Eliminar una fila
Eliminar un pedido concreto por su ID:
DELETE FROM pedidos
WHERE id = 25;Query OK, 1 row affected (0.01 sec)
Se elimina el pedido 25 (el pedido cancelado de Marta). MySQL confirma que 1 fila fue afectada. Si el ID no existiera, "0 rows affected" sin error.
Como la tabla pedidos tiene la restricción ON DELETE CASCADE en su relación con detalle_pedidos, eliminar un pedido también elimina automáticamente sus líneas de detalle. Esto protege la integridad de los datos: no quedan detalles huérfanos apuntando a un pedido que ya no existe.
DELETE con WHERE compuesto
Puedes usar condiciones complejas en el WHERE:
DELETE FROM pedidos
WHERE estado = 'cancelado'
AND fecha_pedido < '2025-12-15';Query OK, 2 rows affected (0.01 sec)
Esto elimina los pedidos cancelados anteriores al 15 de diciembre de 2025. En nuestra base de datos, son los pedidos 16 (Andrés, 699 euros) y 17 (María, 49.99 euros).
DELETE con LIMIT y ORDER BY
Puedes limitar el número de filas eliminadas:
DELETE FROM etiquetas_producto
WHERE etiqueta = 'oferta'
ORDER BY producto_id
LIMIT 1;Query OK, 1 row affected (0.01 sec)
Elimina solo la primera etiqueta 'oferta' ordenada por producto_id. Esto es útil cuando quieres eliminar en lotes controlados o solo el registro más antiguo.
DELETE con subconsulta
Puedes usar subconsultas en el WHERE para identificar qué filas eliminar. Eliminar las reseñas de productos que ya no están activos:
DELETE FROM resenas
WHERE producto_id IN (
SELECT id FROM productos WHERE activo = FALSE
);La subconsulta identifica los productos inactivos y el DELETE elimina sus reseñas. MySQL no permite referenciar directamente la tabla que se está eliminando en una subconsulta (es decir, no puedes hacer DELETE FROM tabla WHERE id IN (SELECT ... FROM tabla)). Para esos casos, necesitas usar una tabla derivada intermedia o un DELETE con JOIN.
DELETE sin WHERE
Un DELETE sin WHERE elimina todas las filas de la tabla pero mantiene la estructura:
-- PELIGRO: elimina TODOS los registros
DELETE FROM etiquetas_producto;Query OK, 29 rows affected (0.01 sec)
La tabla etiquetas_producto queda vacía pero sigue existiendo con su definición de columnas e índices. El AUTO_INCREMENT no se reinicia: si el último ID era 29, el siguiente registro insertado será el 30.
Para eliminar todos los registros y reiniciar el AUTO_INCREMENT, usa TRUNCATE TABLE en su lugar (lo veremos más adelante).
ON DELETE CASCADE
Las claves foráneas con ON DELETE CASCADE propagan la eliminación automáticamente. En nuestra base de datos:
La tabla detalle_pedidos tiene ON DELETE CASCADE en su referencia a pedidos. Al eliminar un pedido, se eliminan automáticamente todos sus detalles.
La tabla resenas tiene ON DELETE CASCADE en su referencia a productos. Al eliminar un producto, se eliminan automáticamente todas sus reseñas.
-- Esto elimina el producto Y todas sus reseñas y etiquetas
DELETE FROM productos WHERE id = 30;El producto 30 (El nombre del viento) se elimina junto con todas sus reseñas y etiquetas. Pero si el producto tiene registros en detalle_pedidos (que tiene ON DELETE RESTRICT), la eliminación falla para proteger el historial de ventas:
-- Esto falla porque el producto tiene ventas registradas
DELETE FROM productos WHERE id = 1;ERROR 1451 (23000): Cannot delete or update a parent row:
a foreign key constraint fails
ON DELETE RESTRICT impide eliminar registros que tienen dependencias. Es la protección correcta para datos históricos que no deberían perderse.
Verificar antes de eliminar
Siempre ejecuta un SELECT con el mismo WHERE antes de hacer el DELETE para confirmar qué filas se eliminarán:
-- Primero ver qué se va a eliminar
SELECT id, estado, total
FROM pedidos
WHERE estado = 'cancelado';
-- Si es correcto, proceder
DELETE FROM pedidos WHERE estado = 'cancelado';Este hábito previene eliminaciones accidentales, especialmente cuando el WHERE es complejo.
Modo seguro
Al igual que con UPDATE, el modo sql_safe_updates impide DELETE sin WHERE:
SET sql_safe_updates = 1;
-- Esto dará error:
DELETE FROM productos;
-- ERROR 1175: You are using safe update mode...Practica con DELETE
Usa el editor para eliminar filas y comprobar el resultado:
En el siguiente artículo veremos cómo usar DELETE con JOIN para eliminar filas basándote en datos de tablas relacionadas.
Escrito por Eduardo Lázaro
