DELETE: borrar filas
En resumen: DELETE FROM … WHERE borra las filas que cumplen la condición; sin WHERE desaparecen todas, y una clave foránea prohíbe borrar una fila a la que apuntan otras.
Problema
Quita mi reseña
En enero Maria escribió una reseña del detergente en polvo: «El paquete llegó roto.» La tienda le envió un paquete nuevo. Ahora Maria escribe a soporte y pide que se quite la reseña.
La fila tiene que desaparecer de reviews. Solo esa, no las otras reseñas de Maria.
La idea
DELETE FROM … WHERE
DELETE FROM dice de qué tabla, y WHERE dice qué filas:
La reseña 7 ya no está, y la otra reseña de Maria, la del pan blanco, sigue ahí. DELETE quita filas enteras. No se listan columnas.
La fila se borra solo en esta base de datos. «Base nueva» la devuelve.
Pruébalo
Una cuenta cerrada
Teodora Genova (cliente 19) se registró en septiembre pero no ha pedido nada. Hoy cierra su cuenta. Bórrala.
Solución
DELETE FROM customers WHERE id = 19;DELETE FROM customers WHERE id = 19. Quedan 19 clientes. Teodora no tiene pedidos ni reseñas, así que la base de datos lo permite. En la tarjeta siguiente es distinto.
Míralo
Un cliente con pedidos
Maria también quiere cerrar su cuenta. Pruébalo:
La base de datos se niega. Maria tiene 12 pedidos y dos reseñas, y apuntan a ella con una clave foránea (customer_id). Si su fila desapareciera, los pedidos no pertenecerían a nadie.
Es una regla de la tabla, como UNIQUE y CHECK de la primera lección. En el módulo siguiente la escribirás tú y elegirás qué pasa con los pedidos cuando se borra al cliente.
Míralo
DELETE sin WHERE
Olvida WHERE y desaparece cada fila:
16 reseñas, reunidas a lo largo de un año entero, desaparecen con una sola sentencia. La tabla se queda, pero vacía. Haz clic en «Base nueva» para recuperarlas.
Con los clientes no funciona así:
La mayoría de los clientes tiene pedidos, así que toda la sentencia se anula. Ni siquiera se borran los clientes sin pedidos: o se ejecuta toda la sentencia, o no se ejecuta nada. Así que la costumbre de la lección anterior vale también aquí: primero un SELECT con el mismo WHERE.
La idea
Borrado lógico (soft delete)
Georgi Petrov cancela su pedido nuevo 57. Borrarlo no funciona, porque el pedido tiene productos:
Podrías borrar primero sus filas de order_items y después el pedido en sí. Pero las tiendas rara vez lo hacen. En su lugar el pedido se cancela:
Esto es un borrado lógico (soft delete): la fila se queda, pero marcada como borrada o cancelada. Por qué lo prefieren las tiendas:
- Los informes siguen siendo correctos. Cuántos pedidos se cancelan, y por qué, es una pregunta importante.
- La contabilidad necesita cada pedido que tuvo un pago.
- Soporte ve el historial cuando llama el cliente.
- Un error se puede arreglar. Lo cancelado vuelve con un
UPDATE. Lo borrado no vuelve.
El precio es que cada consulta tiene que acordarse de los cancelados. El informe de ventas necesita WHERE status <> 'cancelled'.
Más precisamente, para curiosos
En muchos sistemas cada tabla tiene una columna deleted_at: NULL para las filas vivas, una fecha para las «borradas». Entonces cada consulta lleva WHERE deleted_at IS NULL. Cómo añadir una columna a una tabla lo verás en el módulo siguiente.
A veces borrar es obligatorio. Cuando una persona pide que se eliminen sus datos (el «derecho al olvido» del RGPD), los datos personales tienen que irse. A menudo se borran o se sustituyen el nombre y el correo, y los pedidos se quedan sin ellos para las cuentas.
Pruébalo
Sin pepinos
Los pepinos (producto 13) se han agotado. La tienda los quita del pedido nuevo 57, y los demás productos del pedido se quedan.
Solución
DELETE FROM order_items WHERE order_id = 57 AND product_id = 13;DELETE FROM order_items WHERE order_id = 57 AND product_id = 13. Las dos condiciones juntas: sin la primera, los pepinos desaparecerían también de los pedidos antiguos. Se comprueba toda la tabla order_items.
Ejercicio
Dos tareas
1. Boris Mitev (boris.mitev@example.com) quiere que se quiten sus reseñas. Bórralas, encontrando al cliente por el correo con una subconsulta.
Sin las reseñas de Boris:
Solución
DELETE FROM reviews
WHERE customer_id = (SELECT id FROM customers WHERE email = 'boris.mitev@example.com');DELETE FROM reviews WHERE customer_id = (SELECT id FROM customers WHERE email = 'boris.mitev@example.com'). Tiene una reseña, la del café. Quedan 15. A Boris en sí no se le puede borrar: tiene pedidos.
2. La banitsa de queso y los pepinos se han agotado y no volverán antes de fin de mes. Quita los productos agotados (stock 0) de los pedidos nuevos (status = 'new'). Los pedidos antiguos son historial y no se tocan.
Los pedidos nuevos sin los productos agotados:
Solución
DELETE FROM order_items
WHERE product_id IN (SELECT id FROM products WHERE stock = 0)
AND order_id IN (SELECT id FROM orders WHERE status = 'new');DELETE FROM order_items WHERE product_id IN (SELECT id FROM products WHERE stock = 0) AND order_id IN (SELECT id FROM orders WHERE status = 'new'). Desaparecen tres filas, de los pedidos 27, 46 y 57. Sin la segunda condición desaparecerían 18 filas, algunas de pedidos entregados. El campo empieza con un SELECT que las muestra.
Test
Ponte a prueba
Lecciones relacionadas
Sección «Lecciones relacionadas»- Se basa en: Clave primaria y clave foránea · Subconsultas · INSERT: insertar filas · UPDATE: cambiar valores
- Continúa en: Upsert: insertar o cambiar · La base de datos: de CREATE a DROP · Claves foráneas: vínculos entre tablas · Normalización
- Ejercicios sobre el tema: Cambiar los datos