0%

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 in 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 with the two selected values. When no row matches, .fetchone() returns Python None.

For the visible tool result, the tuple positions follow the SELECT : asset tag first, name second. The function does not build that tuple itself. SQLite produces the row, the cursor holds the result, and .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 . The query still has valid SQL, the table still exists, and no database operation has failed. The only difference is that none of the stored rows has category = 'tools'. Seeing None confirms that an empty search is data your program can handle, not an to repair.

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- , and the catalog without tools should return None.