W3docs

Python MySQL UPDATE – Modificar Filas en una Tabla

Aprende a actualizar filas MySQL en Python con mysql-connector-python: consultas parametrizadas, actualizaciones masivas, transacciones y manejo de errores.

Modificar registros existentes es una de las operaciones de base de datos más habituales. Ya sea para corregir una errata, actualizar la dirección de un cliente o marcar un pedido como enviado, la sentencia SQL UPDATE es la herramienta adecuada. Este capítulo muestra cómo ejecutar sentencias UPDATE desde Python usando mysql-connector-python, cubriendo actualizaciones de una sola fila, actualizaciones de varias columnas, actualizaciones masivas con executemany(), el patrón de gestor de contexto y los errores comunes que sorprenden a los principiantes.

Requisitos previos

Antes de ejecutar los ejemplos necesitas lo siguiente:

  • Python 3.8 o posterior instalado
  • mysql-connector-python instalado (pip install mysql-connector-python)
  • Un servidor MySQL en funcionamiento (local o remoto)
  • Una base de datos y una tabla con las que trabajar (consulta MySQL Get Started y MySQL Create Table)

Los ejemplos a continuación asumen que tienes una base de datos llamada mydatabase con una tabla customers creada y poblada en el capítulo MySQL Insert.

La sentencia UPDATE

La sentencia SQL UPDATE cambia los valores de una o más columnas en las filas que cumplen una condición:

UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;

Incluye siempre una cláusula WHERE. Sin ella, se actualizan todas las filas de la tabla. MySQL aplica el cambio de forma silenciosa — no hay ningún aviso de confirmación.

Conectarse a MySQL

Antes de ejecutar cualquier sentencia debes abrir una conexión y crear un cursor. El cursor envía SQL al servidor y recupera los resultados.

import mysql.connector
from mysql.connector import Error

mydb = mysql.connector.connect(
    host="localhost",
    user="yourusername",
    password="yourpassword",
    database="mydatabase"
)

mycursor = mydb.cursor()

Actualizar una sola fila

La forma más segura de apuntar a una fila es una consulta parametrizada. Pasa los valores como una tupla de Python — el conector los escapa antes de enviar la consulta a MySQL, lo que previene la inyección SQL.

import mysql.connector
from mysql.connector import Error

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    mycursor = mydb.cursor()

    sql = "UPDATE customers SET address = %s WHERE address = %s"
    val = ("Park Lane 38", "Highway 37")

    mycursor.execute(sql, val)
    mydb.commit()                       # write the change to disk

    print(mycursor.rowcount, "record(s) affected")

except Error as e:
    print(f"Error: {e}")
    mydb.rollback()                     # undo any partial changes on failure

finally:
    if mydb.is_connected():
        mycursor.close()
        mydb.close()

cursor.rowcount indica cuántas filas se modificaron realmente. Un valor de 0 significa que la condición WHERE no coincidió con ninguna fila — la consulta se ejecutó sin error, pero no se actualizó nada.

Por qué se requiere commit()

mysql-connector-python abre las conexiones con el autocommit desactivado por defecto. Hasta que llames a mydb.commit(), la actualización existe únicamente dentro de tu transacción actual y es invisible para otras conexiones. Si el script falla antes de confirmar, el cambio se revierte automáticamente. Llamar a mydb.rollback() de forma explícita en el bloque except deja clara la intención.

Actualizar varias columnas a la vez

Separa las asignaciones de columnas con comas dentro de la cláusula SET para cambiar varios campos en una sola sentencia:

import mysql.connector
from mysql.connector import Error

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    mycursor = mydb.cursor()

    sql = "UPDATE customers SET name = %s, address = %s WHERE id = %s"
    val = ("John Smith", "Main Street 10", 1)

    mycursor.execute(sql, val)
    mydb.commit()

    print(mycursor.rowcount, "record(s) affected")

except Error as e:
    print(f"Error: {e}")
    mydb.rollback()

finally:
    if mydb.is_connected():
        mycursor.close()
        mydb.close()

Usar la clave primaria (id) en la cláusula WHERE es la forma más fiable de apuntar exactamente a una fila.

Actualizar varias filas en una sola sentencia

Si quieres aplicar el mismo cambio a todas las filas que cumplen una condición, amplía la cláusula WHERE. Una sola llamada a execute() es suficiente:

import mysql.connector
from mysql.connector import Error

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    mycursor = mydb.cursor()

    # Change the city to "Oslo" for every customer on "Park Lane"
    sql = "UPDATE customers SET address = %s WHERE address LIKE %s"
    val = ("Oslo 1", "%Park Lane%")

    mycursor.execute(sql, val)
    mydb.commit()

    print(mycursor.rowcount, "record(s) affected")

except Error as e:
    print(f"Error: {e}")
    mydb.rollback()

finally:
    if mydb.is_connected():
        mycursor.close()
        mydb.close()

Actualizar una lista de filas con executemany()

Cuando tienes una lista de filas para actualizar con valores distintos para cada una, usa executemany(). Ejecuta la misma sentencia parametrizada una vez por elemento en un solo viaje de ida y vuelta, manteniendo todo dentro de una transacción:

import mysql.connector
from mysql.connector import Error

# Each tuple: (new_address, customer_id)
updates = [
    ("Sunset Blvd 1",  3),
    ("Baker Street 2", 7),
    ("Abbey Road 3",   11),
]

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    mycursor = mydb.cursor()

    sql = "UPDATE customers SET address = %s WHERE id = %s"
    mycursor.executemany(sql, updates)
    mydb.commit()

    print(mycursor.rowcount, "record(s) affected")

except Error as e:
    print(f"Error: {e}")
    mydb.rollback()

finally:
    if mydb.is_connected():
        mycursor.close()
        mydb.close()

Dado que executemany() envuelve todas las actualizaciones en una sola transacción, o todas tienen éxito o ninguna lo tiene — nunca acabas con un conjunto de datos parcialmente actualizado.

Usar un gestor de contexto (patrón recomendado)

Abrir la conexión dentro de una sentencia with garantiza que siempre se cierre, incluso si se lanza una excepción a mitad del proceso. Este es el patrón más limpio para código en producción:

import mysql.connector
from mysql.connector import Error

db_config = {
    "host": "localhost",
    "user": "yourusername",
    "password": "yourpassword",
    "database": "mydatabase",
}

try:
    with mysql.connector.connect(**db_config) as mydb:
        with mydb.cursor() as mycursor:
            sql = "UPDATE customers SET address = %s WHERE name = %s"
            mycursor.execute(sql, ("New Road 5", "Alice"))
            mydb.commit()
            print(mycursor.rowcount, "record(s) affected")

except Error as e:
    print(f"Error: {e}")

El bloque with cierra tanto el cursor como la conexión al salir, independientemente de si se lanzó una excepción.

Previsualizar cambios antes de actualizar (prueba en seco)

Antes de ejecutar una actualización que afecte a muchas filas, ejecuta primero un SELECT con la misma cláusula WHERE. Esta prueba en seco te muestra exactamente qué filas se modificarán:

import mysql.connector
from mysql.connector import Error

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    mycursor = mydb.cursor()

    condition = "%Highway%"

    # Dry run: see which rows would be affected
    mycursor.execute(
        "SELECT id, name, address FROM customers WHERE address LIKE %s",
        (condition,)
    )
    rows = mycursor.fetchall()
    print(f"{len(rows)} row(s) would be updated:")
    for row in rows:
        print(row)

    # Proceed only if rows were found
    if rows:
        mycursor.execute(
            "UPDATE customers SET address = %s WHERE address LIKE %s",
            ("New Highway 1", condition)
        )
        mydb.commit()
        print(f"{mycursor.rowcount} row(s) updated")

except Error as e:
    print(f"Error: {e}")
    mydb.rollback()

finally:
    if mydb.is_connected():
        mycursor.close()
        mydb.close()

Errores comunes

Olvidar la cláusula WHERE

# DANGER: updates every row in the table
mycursor.execute("UPDATE customers SET address = %s", ("Wrong Street 1",))
mydb.commit()

Verifica siempre que tu cláusula WHERE esté presente y sea correcta antes de llamar a commit().

Pasar una cadena en lugar de una tupla

# Wrong — iterates over characters of the string
mycursor.execute("UPDATE customers SET address = %s WHERE name = %s", "AliceMain Street")

# Correct — wrap values in a tuple
mycursor.execute("UPDATE customers SET address = %s WHERE name = %s", ("Main Street", "Alice"))

El conector espera una secuencia (tupla o lista) como segundo argumento. Pasar una cadena directa hace que itere sobre los caracteres individuales, lo que provoca un confuso ProgrammingError.

Olvidar commit()

mycursor.execute("UPDATE customers SET address = %s WHERE name = %s", ("Main Street", "Alice"))
# Missing mydb.commit() — the update is silently rolled back when the connection closes

Llama a mydb.commit() después de cada operación de escritura, o establece autocommit=True en la conexión si quieres intencionadamente que cada sentencia se confirme de inmediato.

Usar formato de cadena en lugar de consultas parametrizadas

# UNSAFE — vulnerable to SQL injection
name = input("Enter name: ")
sql = f"UPDATE customers SET address = 'New Road' WHERE name = '{name}'"
mycursor.execute(sql)

# Safe — always use %s placeholders
sql = "UPDATE customers SET address = %s WHERE name = %s"
mycursor.execute(sql, ("New Road", name))

Nunca construyas cadenas SQL con f-strings o concatenación con + usando datos introducidos por el usuario.

Buenas prácticas

  • Usa consultas parametrizadas (marcadores de posición %s) siempre. Esta es la regla más importante — previene la inyección SQL.
  • Incluye siempre una cláusula WHERE y verifícala antes de confirmar. Una WHERE ausente actualiza todas las filas de la tabla.
  • Confirma o revierte de forma explícita. Depender del cierre de la conexión para revertir es confuso. Haz explícito el resultado en tu bloque except.
  • Comprueba rowcount tras la actualización para confirmar que se modificó el número esperado de filas.
  • Usa executemany() para actualizaciones en lote en lugar de iterar con execute(). Es más rápido y mantiene todas las actualizaciones en una sola transacción.
  • Añade índices en las columnas de WHERE. Una actualización que recorre la tabla completa es lenta en conjuntos de datos grandes. Indexa las columnas por las que filtras.
  • Usa transacciones para actualizaciones de varios pasos. Si actualizas filas relacionadas en varias tablas (por ejemplo, actualizar un pedido y sus líneas de pedido juntos), engloba todas las sentencias en una sola transacción para no terminar nunca con datos inconsistentes.

Capítulos relacionados

  • MySQL Get Started — instala el conector y crea tu primera conexión
  • MySQL Create Table — crea las tablas que vas a actualizar
  • MySQL Insert — añade filas antes de practicar cómo modificarlas
  • MySQL Where — domina la cláusula WHERE usada en cada UPDATE
  • MySQL Select — lee filas después de actualizarlas para verificar el resultado
  • MySQL Delete — elimina filas en lugar de modificarlas
  • MySQL Order By — ordena resultados al previsualizar filas antes de una actualización
Was this page helpful?