From 169ea455fc1f1d5e5b6e44cb339ba7ffa9d49c31 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Mon, 4 Nov 2019 08:18:06 -0800 Subject: [PATCH] Added table.delete_where(), closes #62 --- docs/python-api.rst | 11 +++++++++++ sqlite_utils/db.py | 8 ++++++++ tests/test_delete.py | 18 ++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/docs/python-api.rst b/docs/python-api.rst index 374bdc6..cadad15 100644 --- a/docs/python-api.rst +++ b/docs/python-api.rst @@ -396,6 +396,17 @@ The ``delete()`` method takes the primary key of the record. This can be a tuple >>> db["compound_dogs"].delete((5, 3)) +Deleting multiple records +========================= + +You can delete all records in a table that match a specific WHERE statement using ``table.delete_where()``:: + + >>> db = sqlite_utils.Database("dogs.db") + >>> # Delete every dog with age less than 3 + >>> db["dogs"].delete_where("age < ?", [3]): + +Calling ``table.delete_where()`` with no other arguments will delete every row in the table. + Upserting data ============== diff --git a/sqlite_utils/db.py b/sqlite_utils/db.py index 68a2002..a51bba7 100644 --- a/sqlite_utils/db.py +++ b/sqlite_utils/db.py @@ -864,6 +864,14 @@ class Table(Queryable): with self.db.conn: self.db.conn.execute(sql, pk_values) + def delete_where(self, where=None, where_args=None): + if not self.exists: + return [] + sql = "delete from [{}]".format(self.name) + if where is not None: + sql += " where " + where + self.db.conn.execute(sql, where_args or []) + def update(self, pk_values, updates=None, alter=False): updates = updates or {} if not isinstance(pk_values, (list, tuple)): diff --git a/tests/test_delete.py b/tests/test_delete.py index 6758831..1198d06 100644 --- a/tests/test_delete.py +++ b/tests/test_delete.py @@ -12,3 +12,21 @@ def test_delete_pk_table(fresh_db): table.insert({"id": 2}, pk="id") table.delete(1) assert [{"id": 2}] == list(table.rows) + + +def test_delete_where(fresh_db): + table = fresh_db["table"] + for i in range(1, 11): + table.insert({"id": i}, pk="id") + assert 10 == table.count + table.delete_where("id > ?", [5]) + assert 5 == table.count + + +def test_delete_where_all(fresh_db): + table = fresh_db["table"] + for i in range(1, 11): + table.insert({"id": i}, pk="id") + assert 10 == table.count + table.delete_where() + assert 0 == table.count