Daten sicher ändern · Übung
Nur den beabsichtigten Gegenstand löschen
Der tragbare Lautsprecher verlässt den Verleihkatalog. Der aufrufende Code hat das Inventarkennzeichen EL-400 bereits bestätigt. Das Entfernen muss dasselbe Kennzeichen innerhalb der ändernden Anweisung identifizieren und jeden benachbarten Gegenstand unberührt lassen.
Run führt diesen exakten Aufruf über eine offene Verbindung aus:
remove_item(connection, "EL-400")
Öffne catalog_changes.py und finde die neue Funktion unterhalb von change_loan_days:
def remove_item(connection, asset_tag):
statement = """
DELETE FROM items
WHERE asset_tag = ?
"""
connection.execute(statement)
DELETE FROM items benennt die Tabelle, deren Zeilen entfernt werden dürfen. Die Bedingung WHERE asset_tag = ? legt den Wirkungsbereich des Entfernens fest. Im Projekt gibt es kein ausführbares Beispiel ohne WHERE, weil ein unbegrenztes Löschen jede Gegenstandszeile entfernen würde.
Die Anweisung hat einen Platzhalter, und der aufrufende Code liefert einen veränderlichen Wert. Ändere die letzte Zeile zu:
connection.execute(statement, (asset_tag,))
Lies den fertigen Aufruf als kleine Zusage. DELETE FROM items sagt, welche Art von Änderung erlaubt ist. WHERE asset_tag = ? sagt, dass nur eine Zeile mit einem exakten eindeutigen Kennzeichen infrage kommt. (asset_tag,) liefert dieses Kennzeichen, ohne die Anweisung zu verändern. Für "EL-400" passt eine Zeile. Für "NO-404" passt keine. In keinem Fall soll die Datenbank EL-300 berücksichtigen, obwohl es zur selben Kategorie gehört.
Deshalb gehört die Bedingung in die löschende Anweisung selbst. Eine separate Suche kann einer Person helfen, eine Wahl zu bestätigen, aber sie kann eine spätere Anweisung mit breiterem Wirkungsbereich nicht absichern. Die sichere Grenze ist an einer Stelle sichtbar: fester Löschtext plus ein separat gebundener identifizierender Wert.
Wie in find_item macht das Komma aus (asset_tag,) ein Tupel mit einem Element. Das vollständige Kennzeichen bleibt vom SQL getrennt, einschließlich jedes Apostrophs oder SQL-ähnlichen Satzzeichens.
Klicke auf Run und vergleiche die sichtbaren Nachweise:
before EL-400
(6, 'EL-400', 'Portable speaker', 'electronics', 20.5)
remove_item(connection, "EL-400")
None
after EL-400
None
Das erste None ist der vorläufige Rückgabewert der Funktion. Das zweite stammt aus einer neuen Suche nach dem entfernten Kennzeichen und zeigt, dass keine Zeile übrig bleibt. Run probiert auch ein fehlendes Kennzeichen und zeigt danach EL-300 unverändert.
Eine erfolgreiche frühere Vorschau wurde nicht übertragen, um diesen Aufruf zu begrenzen. Das DELETE ist sicher, weil sein eigenes WHERE das eindeutige Kennzeichen vergleicht und sein Wert separat gebunden wird.
Submit verwendet bekannte, fehlende, apostrophhaltige und SQL-ähnliche Kennzeichen mit frischen Katalogen. Es vergleicht nach jedem Versuch die vollständige Menge der Nachbarzeilen. Lösche nicht nach Name oder Kategorie, baue den Katalog nicht nach einer zu breiten Änderung neu auf und öffne keine andere Verbindung.
Daten zu entfernen verdient eine Anweisung, die ihr Ziel selbst erklären kann. Deine sagt jetzt genau, welche Tabelle, welche eindeutig identifizierende Spalte und welcher separat gelieferte Wert das Entfernen steuern.
Aufgabe
Übergib in remove_item das Tupel (asset_tag,) als zweites Argument an die bestehende DELETE-Anweisung. Behalte die präzise Bedingung WHERE asset_tag = ? bei.
Führe das Projekt aus, bestätige, dass das Ziel verschwindet und seine Nachbarzeile bleibt, und reiche es dann ein.