Ir al contenido principal

Modificación y eliminación

Actualización de registros con UPDATE

UPDATE modifica valores de registros que ya existen. No agrega registros ni los elimina: los mismos registros siguen ahí, con algún dato distinto.

UPDATE socios
SET    telefono = '221-5551234'
WHERE  id = 47;

Tres partes, y las tres importan:

Parte Qué define Qué pasa si falta
UPDATE socios Qué tabla se modifica. Error de sintaxis.
SET telefono = ... Qué campos cambian y con qué valores. Error de sintaxis: no se dice qué cambiar.
WHERE id = 47 Qué registros se modifican. Se modifican todos. Sin error y sin aviso.

Fijate en la asimetría de la última fila. Si falta el SET, la base avisa y no ejecuta nada. Si falta el WHERE, la base hace exactamente lo que se le pidió: cambia ese campo en todos los registros. No hay advertencia, no hay confirmación, no hay vuelta atrás.

Para cambiar varios campos a la vez, se separan con comas dentro del mismo SET:

UPDATE socios
SET    correo   = '[email protected]',
       telefono = '221-5551234'
WHERE  id = 47;
Consulta previa al cambio: el socio 47, Ana Pérez, con el teléfono vacío (NULL)
Paso 1: la verificación previa. La grilla muestra que el teléfono de Ana está en NULL y que la condición apunta a un solo registro.
Resultado del UPDATE: el mensaje 1 fila afectada con la consulta que cambia correo y teléfono
Paso 2: el UPDATE cambia los dos campos de una vez y confirma que afectó una fila. Ese número es la comprobación de que el WHERE estuvo bien escrito.
La misma consulta después del cambio: el teléfono ahora dice 221-5551234
Paso 3: la misma consulta de antes, ahora con el teléfono cargado. Solo se modificaron los datos, no la estructura de la tabla.

Eliminación de registros con DELETE

DELETE FROM socios WHERE id = 47;

Es la más corta y tiene un detalle que a primera vista parece una inconsistencia: no dice qué se borra. No hay una lista de columnas como en el SELECT, ni un SET como en el UPDATE. Y no es un olvido: DELETE no borra valores, borra registros completos. Un registro al que le quedan algunos campos no es un registro: es un dato a medias. Cuando se da de baja algo, se lo da de baja entero.

Conviene no confundir las tres instrucciones que «borran», porque hacen cosas muy distintas:

Instrucción Qué elimina La tabla después
DELETE FROM socios Los registros. Sigue existiendo, vacía.
TRUNCATE TABLE socios Los registros, todos y de golpe. Sigue existiendo, vacía. Más rápido, y reinicia el contador de AUTO_INCREMENT.
DROP TABLE socios La tabla misma, con sus campos y sus reglas. No existe. No hay dónde cargar socios hasta crear otra.

Y un detalle que sorprende a quien viene de usar programas: después de un UPDATE o un DELETE, el gestor informa cuántos registros quedaron afectados —«1 fila afectada», «30 filas afectadas»—. Ese número hay que leerlo. Es la única señal que va a haber de que la sentencia hizo lo que se esperaba, o de que hizo mucho más. Un «247 filas afectadas» cuando se esperaba modificar una es la forma de enterarse de que el WHERE estaba mal escrito, todavía a tiempo de intentar arreglarlo.

La importancia del WHERE

Vale entender por qué pasa, porque el motivo no es la distracción sino la forma en que se escribe la sentencia. Uno piensa primero qué quiere cambiar —el teléfono de Ana— y escribe el SET con eso. Después se acuerda de acotar a quién, y escribe el WHERE al final. Y en el medio hay un momento en que la sentencia está completa para el gestor pero no para uno: si se selecciona todo y se ejecuta en ese instante, ya no hay vuelta atrás.

La defensa es un cambio de hábito, y es simple: escribir primero la parte que acota. Antes de pensar en el SET o en el DELETE, escribir la condición. La sentencia queda incompleta —falta decir qué cambia— y el gestor se va a negar a ejecutarla. Es imposible ejecutar algo destructivo por accidente, porque no hay nada que ejecutar.

Y hay un segundo motivo por el que el WHERE de estas dos instrucciones es más delicado que el de un SELECT: un SELECT con la condición mal escrita devuelve un resultado equivocado, que se ve raro y se corrige. Un UPDATE con la condición mal escrita cambia los datos, y el resultado equivocado queda guardado. La misma línea de texto, dos consecuencias incomparables.

Verificación previa con una consulta SELECT

Acá está el método que evita el problema, y no cuesta nada. Es la aplicación de una idea sencilla: si la misma condición se prueba antes, la operación deja de ser a ciegas.

-- Paso 1: ¿a quiénes va a afectar? Se comprueba con un SELECT.
SELECT id, nombre, telefono FROM socios WHERE id = 47;

-- Paso 2: recién ahora, con la condición ya escrita y probada, la operación.
UPDATE socios SET telefono = '221-5551234' WHERE id = 47;

El SELECT del primer paso se escribe copiando el WHERE que se va a usar, y cumple tres funciones a la vez:

  • Confirma que la condición identifica lo que uno cree. Si devuelve un registro, era eso lo que se buscaba. Si devuelve tres, la condición es más amplia de lo que se pensaba.
  • Si devuelve cero, avisa antes de tocar nada. Una condición que no encuentra nada probablemente esté mal escrita: un nombre mal tipeado, un id que no existe. En lugar de ejecutar una operación que no hace nada, uno se entera del problema.
  • Deja ver los valores actuales. Es lo único que permite saber si el cambio tiene sentido: quizá el teléfono ya era ese.

Para una operación masiva hay una variante que aporta más información todavía: contar los registros afectados antes.

-- ¿A cuántos va a afectar exactamente? Un número, no una lista.
SELECT COUNT(*) FROM socios WHERE activo = 0 AND alta < '2020-01-01';

Ese número es el que después hay que comparar con el «N filas afectadas» que informa el gestor. Si coinciden, la operación hizo lo previsto. Si no coinciden, algo pasó. Y para el caso extremo —una corrección masiva, un borrado por lote— existe una tercera red de seguridad que se vio en la Unidad 1: las transacciones. Encerrando la operación entre un inicio y un COMMIT, si el resultado no es el esperado se descarta todo con un ROLLBACK y los datos vuelven a como estaban. Para el trabajo diario no hace falta; para una operación que toca miles de registros, es la diferencia entre poder arrepentirse y no poder.

Resultado de COUNT(*) con la condición activo = 0 y alta anterior a 2020: devuelve 5
La misma idea, pero pidiendo un número en lugar de una lista: 5 registros van a quedar afectados. Una operación masiva se decide con este dato, no después.

Resumen

  • UPDATE tabla SET campo = valor WHERE condición modifica registros existentes.
  • DELETE FROM tabla WHERE condición elimina registros completos: por eso no lleva lista de campos.
  • Sin WHERE un UPDATE modifica todo y un DELETE borra todo, sin aviso.
  • DELETE FROM vacía la tabla pero la deja; TRUNCATE hace lo mismo más rápido; DROP TABLE elimina la tabla misma.
  • El «N filas afectadas» que informa el gestor hay que leerlo: es la única señal de que la sentencia hizo lo que se esperaba.
  • El error pasa porque uno escribe primero qué cambia y después a quién: conviene escribir primero la condición.
  • Un SELECT mal filtrado devuelve un resultado raro; un UPDATE mal filtrado cambia los datos.
  • Antes de operar: probar la condición con un SELECT.
  • Para operaciones masivas: COUNT(*) antes y transacción con COMMIT y ROLLBACK.

Ver las funciones de agregación