7.9.21. SQL-20 — DELETE

Six flavours, mirroring UPDATE:

Form

When to use

db |> delete_(row)

by-PK from a loaded struct (non-PK fields ignored)

db |> delete_by_id(type<T>, id)

by-PK when you only have the id

db |> _sql_delete(type<T>, where)

bulk via predicate macro

db |> _sql_delete_returning(...)

bulk + capture rows BEFORE they vanish

db |> exec(sql)

raw escape hatch

db |> try_delete_* / _sql_try_delete*

non-panic Result variants

7.9.21.1. Naming

The function form is delete_ (trailing underscore) because delete is a daslang keyword. The macro form uses the _sql_ prefix and skips the underscore (_sql_delete). delete_by_id and try_delete_by_id are separate helpers for the “I just have the id” case so callers don’t have to construct a dummy struct just to identify the row.

As with UPDATE, 0 rows-affected is not an error — the row simply wasn’t there. Reserve Err from try_ variants for SQL failures.

7.9.21.2. By-PK from a row

Useful when you already have the row loaded (e.g. from a SELECT).

let n1 = db |> delete_(User(Id = 2, Name = "", Active = false))
// DELETE FROM "Users" WHERE "Id" = ?

7.9.21.3. By-PK from just an id

No dummy struct construction — pass the id directly.

let n2 = db |> delete_by_id(type<User>, 4)
// DELETE FROM "Users" WHERE "Id" = ?

7.9.21.4. Bulk delete via the macro

Captured-var binds and _.Col references both work.

let purged = db |> _sql_delete(type<User>, !_.Active)
// DELETE FROM "Users" WHERE NOT ("Active")

7.9.21.5. Bulk RETURNING — capture rows BEFORE they vanish

Useful for audit logs, undo queues, “delete-and-publish” pipelines.

let small_threshold = 75
let removed_orders <- db |> _sql_delete_returning(type<Order>,
                                                  _.Total < small_threshold)
// DELETE FROM "Orders" WHERE "Total" < ?
//   RETURNING "Id", "UserId", "Total"

7.9.21.6. Raw-SQL escape hatch

exec runs arbitrary SQL with no parameter binding. For dynamic values stick to the macro forms above; this hatch is for migrations / DDL / statements the macro can’t translate.

db |> exec("DELETE FROM Users WHERE Name LIKE 'a%'")

7.9.21.7. Non-panic try_ variants

let attempt = db |> try_delete_by_id(type<User>, 999)
if (attempt |> is_err) {
    // SQL failure (constraint / IO / BUSY)
} else {
    let n = attempt |> unwrap   // 0 if id didn't match
}

See also

Full source: tutorials/sql/20-delete.das

Previous tutorial: SQL-19 — UPDATE

Next tutorial: SQL-21 — UPSERT