Hoofdstuk 5 · oefening
Wijzig gegevens veilig
Bind een waarde aan een bekende query
De catalogus kan een vaste vraag beantwoorden, maar een echt programma moet zoeken naar elke inventariscode die de aanroeper opgeeft. Voor deze uitvoering roept Python de nieuwe functie aan met een zichtbare code:
find_item(connection, "TL-100")
De argumenten zijn een al geopende connection en de tekstwaarde "TL-100". Open catalog_changes.py. De functie bevat al een volledige query waarvan de WHERE-voorwaarde een vraagteken heeft:
def find_item(connection, asset_tag):
statement = """
SELECT id, asset_tag, name, category, loan_days
FROM items
WHERE asset_tag = ?
"""
return connection.execute(statement).fetchone()
De ? is een placeholder voor één waarde. De SQL-structuur blijft vast terwijl Python de waarde afzonderlijk opgeeft. Verander alleen de returnregel:
return connection.execute(statement, (asset_tag,)).fetchone()
De aanroep van execute heeft nu twee argumenten: de instructie en een tuple met één element die de zoekwaarde bevat.
| Positie in SQL | Waarde van het Python-argument |
|---|---|
eerste en enige ?, voor asset_tag | eerste en enige element van (asset_tag,) |
Volg de waarde één keer door de aanroep. Python ontvangt "TL-100" als asset_tag. De instructie bevat nog steeds WHERE asset_tag = ?; Python plakt de code niet in die tekst. In plaats daarvan geeft (asset_tag,) de waarde "TL-100" naast de instructie door en koppelt de database die eerste tuplewaarde aan de eerste placeholder. Een code met een apostrof volgt precies dezelfde weg. Een ontbrekende code ook: die levert simpelweg geen passende rij op. Door deze scheiding kan één instructie alle drie de gevallen afhandelen zonder van vorm te veranderen.
Ook de meegegeven connection is van belang. run_changes.py heeft die al geopend en de zichtbare catalogus klaargezet. Door via diezelfde verbinding uit te voeren, stelt de functie een vraag aan de verwachte catalogus in plaats van ongemerkt ergens anders een andere te maken.
De komma in (asset_tag,) is van belang. Haakjes alleen kunnen één waarde groeperen, maar de komma maakt er een tuple met één element van die de database-interface aan één placeholder kan koppelen.
Druk op Run en zoek de twee exacte aanroepen:
== catalog_changes.py: find_item ==
find_item(connection, "TL-100")
(3, 'TL-100', 'Cordless drill', 'tools', 7)
find_item(connection, "NO-404")
None
Het eerste resultaat volgt de volgorde van de geselecteerde kolommen. De tweede aanroep gebruikt dezelfde instructie met een andere waarde en ontvangt None, omdat geen enkele rij voldoet.
run_changes.py maakt voor elke genoemde functie een nieuwe catalogus klaar en drukt de aanroep en het relevante resultaat af. Laat dat bestand ongewijzigd; je functie blijft in catalog_changes.py en gebruikt de verbinding die ze ontvangt.
Submit probeert gewone codes, ontbrekende codes, apostrofs en tekst die op SQL lijkt. Houd de volledige waarde buiten de instructiestring en geef die ongewijzigd door in het tweede argument. Je functie heeft nu één stabiele query die veilig naar veel verschillende waarden kan zoeken.
Opdracht
Geef in catalog_changes.py de tuple (asset_tag,) door als tweede argument aan connection.execute(statement, ...). Behoud de vaste query en geef .fetchone() terug.
Voer het project uit, controleer beide aanroepen en stuur de functie in.