0%

Change Data Safely · practice

Delete Only the Intended Item

The portable speaker is leaving the lending catalog. The caller has already confirmed asset tag EL-400; the removal must identify that same tag inside the changing statement and leave every neighboring item untouched.

Run will make this exact call through an open connection:

remove_item(connection, "EL-400")

Open catalog_changes.py and find the new below change_loan_days:

def remove_item(connection, asset_tag):
    statement = """
        DELETE FROM items
        WHERE asset_tag = ?
    """
    connection.execute(statement)

DELETE FROM items names the table whose rows may be removed. Its WHERE asset_tag = ? gives the removal its . There is no executable example without WHERE in the project, because an unqualified delete would remove every item row.

The statement has one placeholder, and the caller supplies one changing . Change the final line to:

connection.execute(statement, (asset_tag,))

Read the finished call as a small promise. DELETE FROM items says what kind of change is allowed. WHERE asset_tag = ? says that only a row with one exact unique tag may qualify. (asset_tag,) supplies that tag without changing the statement. For "EL-400", one row qualifies. For "NO-404", none do. In neither case should the database consider EL-300, even though it belongs to the same category.

This is why the condition belongs in the deleting statement itself. A separate search can help a person confirm a choice, but it cannot protect a later statement that has broader scope. The safe boundary is visible in one place: fixed delete text plus one separately bound identifying value.

As in find_item, the comma makes (asset_tag,) a one-item . The complete tag remains separate from the SQL, including any apostrophe or SQL-looking punctuation.

Press Run and compare the visible evidence:

before EL-400
(6, 'EL-400', 'Portable speaker', 'electronics', 20.5)
remove_item(connection, "EL-400")
None
after EL-400
None

The first None is the function’s temporary . The second is a fresh search for the removed tag, showing that no row remains. Run also tries a missing tag and then shows EL-300 unchanged.

A successful preview from earlier did not carry over and constrain this call. The DELETE is safe because its own WHERE compares the unique tag and its value is bound separately.

Submit uses known, missing, apostrophe-containing, and SQL-looking tags on fresh catalogs. It compares the complete neighbor set after each attempt. Do not delete by name or category, rebuild the catalog after a broad change, or open another connection.

Removing data deserves a statement that can explain its target on its own. Yours now says exactly which table, which unique identifying column, and which separately supplied value control the removal.

Task

In remove_item, pass (asset_tag,) as the second to the existing DELETE statement. Keep the precise WHERE asset_tag = ? .

Run the project, confirm that the target disappears and its neighbor remains, then submit it.