W3docs

Python MySQL UPDATE – Modificar Linhas em uma Tabela

Aprenda a atualizar linhas MySQL em Python com mysql-connector-python, usando consultas parametrizadas, atualizações em lote e tratamento de erros.

Modificar registros existentes é uma das operações de banco de dados mais comuns. Seja para corrigir um erro de digitação, atualizar o endereço de um cliente ou marcar um pedido como enviado, a instrução SQL UPDATE é a ferramenta certa para isso. Este capítulo mostra como executar instruções UPDATE a partir do Python usando mysql-connector-python, abordando atualizações de linha única, atualizações de várias colunas, atualizações em lote com executemany(), o padrão de gerenciador de contexto e os erros comuns que pegam iniciantes de surpresa.

Pré-requisitos

Você precisa do seguinte antes de executar os exemplos:

  • Python 3.8 ou posterior instalado
  • mysql-connector-python instalado (pip install mysql-connector-python)
  • Um servidor MySQL em execução (local ou remoto)
  • Um banco de dados e uma tabela para trabalhar (consulte MySQL Get Started e MySQL Create Table)

Os exemplos abaixo assumem que você tem um banco de dados chamado mydatabase que contém uma tabela customers criada e preenchida no capítulo MySQL Insert.

A Instrução UPDATE

A instrução SQL UPDATE altera os valores de uma ou mais colunas nas linhas que correspondem a uma condição:

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

Sempre inclua uma cláusula WHERE. Sem ela, todas as linhas da tabela são atualizadas. O MySQL aplica a alteração silenciosamente — não há prompt de confirmação.

Conectando ao MySQL

Antes de executar qualquer instrução, você deve abrir uma conexão e criar um cursor. O cursor envia SQL ao servidor e recupera os resultados.

import mysql.connector
from mysql.connector import Error

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

mycursor = mydb.cursor()

Atualizando uma Única Linha

A maneira mais segura de selecionar uma linha é por meio de uma consulta parametrizada. Passe os valores como uma tupla Python — o conector os escapa antes de enviar a consulta ao MySQL, o que evita injeção 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 informa quantas linhas foram realmente alteradas. Um valor 0 significa que a condição WHERE não correspondeu a nada — a consulta foi executada sem erro, mas nada foi atualizado.

Por que commit() é necessário

mysql-connector-python abre conexões com autocommit desativado por padrão. Até que você chame mydb.commit(), a atualização existe apenas dentro da sua transação atual e é invisível para outras conexões. Se o script travar antes do commit, a alteração é automaticamente revertida. Chamar mydb.rollback() explicitamente no bloco except deixa a intenção clara.

Atualizando Várias Colunas ao Mesmo Tempo

Separe as atribuições de coluna com vírgulas dentro da cláusula SET para alterar vários campos em uma única instrução:

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 a chave primária (id) na cláusula WHERE é a maneira mais confiável de selecionar exatamente uma linha.

Atualizando Várias Linhas em Uma Instrução

Se você quiser aplicar a mesma alteração a todas as linhas que correspondem a uma condição, amplie a cláusula WHERE. Uma única chamada execute() é 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()

Atualizando uma Lista de Linhas com executemany()

Quando você tem uma lista de linhas para atualizar com valores diferentes para cada uma, use executemany(). Ele executa a mesma instrução parametrizada uma vez por item em uma única ida e volta ao servidor, mantendo tudo dentro de uma transação:

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()

Como executemany() envolve todas as atualizações em uma única transação, ou todas têm êxito ou nenhuma tem — você nunca acaba com um conjunto de dados parcialmente atualizado.

Usando um Gerenciador de Contexto (Padrão Recomendado)

Abrir a conexão dentro de uma instrução with garante que ela seja sempre fechada, mesmo que uma exceção seja levantada no meio do caminho. Este é o padrão mais limpo para código em produção:

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}")

O bloco with fecha tanto o cursor quanto a conexão quando o bloco termina, independentemente de uma exceção ter sido levantada.

Pré-visualizando Alterações Antes de Atualizar (Execução a Seco)

Antes de executar uma atualização que afeta muitas linhas, execute um SELECT com a mesma cláusula WHERE primeiro. Esta execução a seco mostra exatamente quais linhas serão alteradas:

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()

Erros Comuns

Esquecer a cláusula WHERE

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

Sempre verifique se a sua cláusula WHERE está presente e correta antes de chamar commit().

Passar uma string em vez de uma 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"))

O conector espera uma sequência (tupla ou lista) como segundo argumento. Passar uma string simples faz com que ele itere sobre os caracteres individuais, gerando um ProgrammingError confuso.

Esquecer de chamar 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

Chame mydb.commit() após cada operação de escrita, ou defina autocommit=True na conexão se você quiser que cada instrução seja confirmada imediatamente.

Usar formatação de string em vez 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 construa strings SQL com f-strings ou concatenação + usando dados fornecidos pelo usuário.

Boas Práticas

  • Use consultas parametrizadas (placeholders %s) sempre. Esta é a regra mais importante — ela previne injeção SQL.
  • Sempre inclua uma cláusula WHERE e verifique-a antes de confirmar. Uma WHERE ausente atualiza todas as linhas da tabela.
  • Confirme ou reverta explicitamente. Depender do fechamento da conexão para reverter é confuso. Torne o resultado explícito no seu bloco except.
  • Verifique rowcount após a atualização para confirmar que o número esperado de linhas foi alterado.
  • Use executemany() para atualizações em lote em vez de fazer um loop com execute(). É mais rápido e mantém todas as atualizações em uma transação.
  • Adicione índices nas colunas do WHERE. Uma atualização que varre a tabela inteira é lenta em grandes conjuntos de dados. Indexe as colunas pelas quais você filtra.
  • Use transações para atualizações de várias etapas. Se você atualizar linhas relacionadas em várias tabelas (por exemplo, atualizando um pedido e seus itens juntos), envolva todas as instruções em uma transação para nunca acabar com dados inconsistentes.

Capítulos Relacionados

  • MySQL Get Started — instale o conector e crie sua primeira conexão
  • MySQL Create Table — crie as tabelas que você vai atualizar
  • MySQL Insert — adicione linhas antes de praticar a alteração delas
  • MySQL Where — domine a cláusula WHERE usada em todo UPDATE
  • MySQL Select — leia as linhas após atualizá-las para verificar o resultado
  • MySQL Delete — remova linhas em vez de modificá-las
  • MySQL Order By — ordene os resultados ao pré-visualizar linhas antes de uma atualização
Was this page helpful?