Ask Precise Questions · practice
When a Query Finds No Row
A tool search can have two perfectly ordinary outcomes: one matching row, or no matching row at all. Python needs a result shape for both cases so the program can respond without treating an empty search as a broken database.
The project calls the first_tool.py like this:
first_tool(connection)
connection already holds an open catalog. The function sends this complete, fixed query through that connection:
cursor = connection.execute(
"""
SELECT asset_tag, name
FROM items
WHERE category = 'tools'
ORDER BY asset_tag ASC
LIMIT 1
"""
)
The call to connection.execute(...) gives the SQL statement to SQLite. The returned cursor represents this query’s result. It does not yet mean that Python has taken a row from that result.
Open first_tool.py. Its final line currently says return None. Change only that line:
return cursor.fetchone()
The .fetchone() call asks for one row. When the catalog contains tools, that row arrives as a .fetchone() returns Python None.
For the visible tool result, the tuple positions follow the SELECT .fetchone() moves one result row into Python.
Press Run. After the existing search.sql section, find these two calls:
== first_tool.py ==
first_tool(connection) with tools
('TL-100', 'Cordless drill')
first_tool(connection) without tools
None
Each call receives a separate open connection. The first catalog has tool rows; the second deliberately has none. The function and its literal SQL stay exactly the same.
Before you run it, predict the second printed category = 'tools'. Seeing None confirms that an empty search is data your program can handle, not an
Python None here means that the query produced zero rows. It is different from SQL NULL, which is a value that can appear inside a row. A row such as ('TL-100', NULL) would still be a row and would reach Python as a tuple containing None. This exercise returns no tuple at all when there is no tool.
Keep the caller in view when you read that distinction. Code using first_tool(connection) can ask if result is None before trying to read tuple positions. It receives one predictable Python shape for each possible outcome.
Submit tries different tags and insertion orders. Keep the supplied ordering and limit so “first” remains predictable, and return the value from .fetchone() rather than the cursor or a list of rows.
An empty answer is still a valid answer. Your function now gives its caller one tuple when a tool exists and a clear None when it does not.
Task
In first_tool.py, change the final line to return cursor.fetchone().
Run the project and check both printed calls: one should return a two-None.