Wijzig gegevens veilig · oefening
Verwijder alleen het bedoelde voorwerp
De draagbare luidspreker verlaat de uitleencatalogus. De aanroeper heeft inventariscode EL-400 al bevestigd; het verwijderen moet diezelfde code binnen de wijzigingsinstructie aanwijzen en elk ander voorwerp intact laten.
Run voert deze exacte aanroep uit via een open verbinding:
remove_item(connection, "EL-400")
Open catalog_changes.py en zoek de nieuwe functie onder change_loan_days:
def remove_item(connection, asset_tag):
statement = """
DELETE FROM items
WHERE asset_tag = ?
"""
connection.execute(statement)
DELETE FROM items noemt de tabel waaruit rijen mogen worden verwijderd. De voorwaarde WHERE asset_tag = ? begrenst het verwijderen. Er staat geen uitvoerbaar voorbeeld zonder WHERE in het project, omdat een delete zonder beperking elke voorwerprij zou verwijderen.
De instructie heeft één placeholder en de aanroeper geeft één veranderende waarde op. Verander de laatste regel in:
connection.execute(statement, (asset_tag,))
Lees de voltooide aanroep als een kleine belofte. DELETE FROM items zegt welk soort wijziging is toegestaan. WHERE asset_tag = ? zegt dat alleen een rij met één exacte, unieke code in aanmerking mag komen. (asset_tag,) geeft die code door zonder de instructie te veranderen. Voor "EL-400" voldoet één rij. Voor "NO-404" geen enkele. In geen van beide gevallen mag de database EL-300 meenemen, ook al hoort die bij dezelfde categorie.
Daarom hoort de voorwaarde in de verwijderinstructie zelf. Een aparte zoekopdracht kan iemand helpen een keuze te bevestigen, maar beschermt geen latere instructie die meer rijen kan raken. De veilige begrenzing is op één plek zichtbaar: vaste deletetekst plus één afzonderlijk gebonden identificerende waarde.
Net als in find_item maakt de komma van (asset_tag,) een tuple met één element. De volledige code blijft apart van de SQL, inclusief elke apostrof of elk leesteken dat op SQL lijkt.
Druk op Run en vergelijk het zichtbare bewijs:
before EL-400
(6, 'EL-400', 'Portable speaker', 'electronics', 20.5)
remove_item(connection, "EL-400")
None
after EL-400
None
De eerste None is de tijdelijke teruggegeven waarde van de functie. De tweede is een nieuwe zoekopdracht naar de verwijderde code, die laat zien dat er geen rij meer is. Run probeert ook een ontbrekende code en toont daarna EL-300 ongewijzigd.
Een geslaagde voorafgaande controle is niet meegenomen om deze aanroep te begrenzen. De DELETE is veilig omdat de eigen WHERE de unieke code vergelijkt en de waarde afzonderlijk is gebonden.
Submit gebruikt bekende, ontbrekende, apostrofbevattende en op SQL lijkende codes op nieuwe catalogussen. Na elke poging vergelijkt het de volledige verzameling andere voorwerpen. Verwijder niet op naam of categorie, bouw de catalogus niet opnieuw op na een te brede wijziging en open geen andere verbinding.
Gegevens verwijderen vraagt om een instructie die haar doel zelfstandig kan uitleggen. Die van jou zegt nu precies welke tabel, welke uniek identificerende kolom en welke afzonderlijk opgegeven waarde het verwijderen bepalen.
Opdracht
Geef in remove_item de tuple (asset_tag,) door als tweede argument aan de bestaande DELETE-instructie. Behoud de precieze voorwaarde WHERE asset_tag = ?.
Voer het project uit, controleer of het doel verdwijnt en het andere voorwerp blijft staan en stuur het daarna in.