W3docs

Python MySQL UPDATE – Zeilen in einer Tabelle ändern

MySQL-Zeilen in Python aktualisieren mit mysql-connector-python: parametrisierte Abfragen, Massenaktualisierungen, Transaktionen und Fehlerbehandlung.

Das Ändern vorhandener Datensätze ist eine der häufigsten Datenbankoperationen. Ob Sie einen Tippfehler korrigieren, die Adresse eines Kunden aktualisieren oder eine Bestellung als versandt markieren – die SQL-Anweisung UPDATE ist das richtige Werkzeug dafür. Dieses Kapitel zeigt, wie Sie UPDATE-Anweisungen aus Python heraus mit mysql-connector-python ausführen. Es werden Einzelzeilenaktualisierungen, Mehrspaltenaktualisierungen, Massenaktualisierungen mit executemany(), das Kontextmanager-Muster und die typischen Fehler, die Einsteigern passieren, behandelt.

Voraussetzungen

Bevor Sie die Beispiele ausführen, benötigen Sie Folgendes:

  • Python 3.8 oder höher ist installiert
  • mysql-connector-python ist installiert (pip install mysql-connector-python)
  • Ein laufender MySQL-Server (lokal oder remote)
  • Eine Datenbank und eine Tabelle zum Arbeiten (siehe MySQL Get Started und MySQL Create Table)

Die folgenden Beispiele setzen voraus, dass Sie eine Datenbank namens mydatabase haben, die eine customers-Tabelle enthält, die im Kapitel MySQL Insert erstellt und befüllt wurde.

Die UPDATE-Anweisung

Die SQL-Anweisung UPDATE ändert die Werte einer oder mehrerer Spalten in Zeilen, die einer Bedingung entsprechen:

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

Fügen Sie immer eine WHERE-Klausel ein. Ohne sie wird jede Zeile in der Tabelle aktualisiert. MySQL wendet die Änderung still an – es gibt keine Bestätigungsaufforderung.

Verbindung zu MySQL herstellen

Bevor Sie eine Anweisung ausführen, müssen Sie eine Verbindung öffnen und einen Cursor erstellen. Der Cursor sendet SQL an den Server und ruft Ergebnisse ab.

import mysql.connector
from mysql.connector import Error

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

mycursor = mydb.cursor()

Eine einzelne Zeile aktualisieren

Der sicherste Weg, eine Zeile gezielt anzusprechen, ist eine parametrisierte Abfrage. Übergeben Sie Werte als Python-Tupel – der Connector escapt sie, bevor die Abfrage an MySQL gesendet wird, was SQL-Injection verhindert.

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 gibt an, wie viele Zeilen tatsächlich geändert wurden. Ein Wert von 0 bedeutet, dass die WHERE-Bedingung nichts gefunden hat – die Abfrage wurde fehlerfrei ausgeführt, aber nichts wurde aktualisiert.

Warum commit() erforderlich ist

mysql-connector-python öffnet Verbindungen standardmäßig mit deaktiviertem Autocommit. Bis Sie mydb.commit() aufrufen, existiert die Aktualisierung nur innerhalb Ihrer aktuellen Transaktion und ist für andere Verbindungen unsichtbar. Wenn das Skript vor dem Commit abstürzt, wird die Änderung automatisch zurückgerollt. Das explizite Aufrufen von mydb.rollback() im except-Block macht die Absicht deutlich.

Mehrere Spalten gleichzeitig aktualisieren

Trennen Sie Spaltenzuweisungen durch Kommas innerhalb der SET-Klausel, um mehrere Felder in einer einzigen Anweisung zu ändern:

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

Die Verwendung des Primärschlüssels (id) in der WHERE-Klausel ist die zuverlässigste Methode, um genau eine Zeile anzusprechen.

Mehrere Zeilen in einer Anweisung aktualisieren

Wenn Sie dieselbe Änderung auf alle Zeilen anwenden möchten, die einer Bedingung entsprechen, erweitern Sie die WHERE-Klausel. Ein einzelner execute()-Aufruf reicht aus:

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

Eine Liste von Zeilen mit executemany() aktualisieren

Wenn Sie eine Liste von Zeilen mit unterschiedlichen Werten aktualisieren möchten, verwenden Sie executemany(). Es führt dieselbe parametrisierte Anweisung einmal pro Element in einem einzigen Roundtrip aus und hält alles innerhalb einer Transaktion:

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

Da executemany() alle Aktualisierungen in eine einzige Transaktion einbettet, gelingen entweder alle oder keine – Sie erhalten nie einen teilweise aktualisierten Datensatz.

Einen Kontextmanager verwenden (empfohlenes Muster)

Das Öffnen der Verbindung innerhalb einer with-Anweisung stellt sicher, dass sie immer geschlossen wird, selbst wenn mitten im Prozess eine Ausnahme ausgelöst wird. Dies ist das sauberste Muster für Produktionscode:

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

Der with-Block schließt sowohl den Cursor als auch die Verbindung, wenn der Block verlassen wird – unabhängig davon, ob eine Ausnahme ausgelöst wurde.

Änderungen vor der Aktualisierung vorprüfen (Probelauf)

Bevor Sie eine Aktualisierung ausführen, die viele Zeilen betrifft, führen Sie zuerst ein SELECT mit derselben WHERE-Klausel aus. Dieser Probelauf zeigt Ihnen genau, welche Zeilen geändert werden:

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

Häufige Fehler

Die WHERE-Klausel vergessen

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

Vergewissern Sie sich immer, dass Ihre WHERE-Klausel vorhanden und korrekt ist, bevor Sie commit() aufrufen.

Einen string statt eines Tupels übergeben

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

Der Connector erwartet eine Sequenz (Tupel oder Liste) als zweites Argument. Wird ein bloßer string übergeben, iteriert er über einzelne Zeichen, was zu einem verwirrenden ProgrammingError führt.

commit() vergessen

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

Rufen Sie mydb.commit() nach jeder Schreiboperation auf, oder setzen Sie autocommit=True für die Verbindung, wenn Sie möchten, dass jede Anweisung sofort committed wird.

String-Formatierung statt parametrisierter Abfragen verwenden

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

Bauen Sie SQL-Strings niemals mit f-Strings oder +-Verkettung aus benutzerseitig eingegebenen Daten zusammen.

Best Practices

  • Verwenden Sie parametrisierte Abfragen (%s-Platzhalter) zu jeder Zeit. Dies ist die wichtigste Regel – sie verhindert SQL-Injection.
  • Fügen Sie immer eine WHERE-Klausel ein und überprüfen Sie diese vor dem Commit. Eine fehlende WHERE-Klausel aktualisiert jede Zeile in der Tabelle.
  • Committen oder Rollback explizit durchführen. Es ist verwirrend, sich darauf zu verlassen, dass das Schließen der Verbindung einen Rollback auslöst. Machen Sie das Ergebnis in Ihrem except-Block explizit.
  • Prüfen Sie rowcount nach der Aktualisierung, um zu bestätigen, dass die erwartete Anzahl von Zeilen geändert wurde.
  • Verwenden Sie executemany() für Massenaktualisierungen anstatt in einer Schleife über execute() zu iterieren. Es ist schneller und hält alle Aktualisierungen in einer Transaktion.
  • Fügen Sie Indizes für WHERE-Spalten hinzu. Eine Aktualisierung, die die gesamte Tabelle durchsucht, ist bei großen Datensätzen langsam. Indizieren Sie die Spalten, nach denen Sie filtern.
  • Verwenden Sie Transaktionen für mehrstufige Aktualisierungen. Wenn Sie zusammenhängende Zeilen über mehrere Tabellen hinweg aktualisieren (z. B. eine Bestellung und ihre Positionen gemeinsam), fassen Sie alle Anweisungen in einer Transaktion zusammen, damit Sie nie inkonsistente Daten erhalten.

Verwandte Kapitel

  • MySQL Get Started — Connector installieren und erste Verbindung herstellen
  • MySQL Create Table — Tabellen erstellen, die Sie aktualisieren werden
  • MySQL Insert — Zeilen einfügen, bevor Sie das Ändern üben
  • MySQL Where — die WHERE-Klausel meistern, die in jedem UPDATE verwendet wird
  • MySQL Select — Zeilen nach der Aktualisierung lesen, um das Ergebnis zu prüfen
  • MySQL Delete — Zeilen entfernen statt sie zu ändern
  • MySQL Order By — Ergebnisse sortieren, wenn Zeilen vor einer Aktualisierung vorgeprüft werden
Was this page helpful?