DELETE Queries
Complete guide to DELETE query building with sqlo.
Basic DELETE
Simple Delete
from sqlo import Q
# ❌ ERROR: DELETE requires WHERE clause or explicit confirmation
try:
query = Q.delete_from("users")
sql, params = query.build()
except ValueError as e:
print(e) # "DELETE without WHERE clause would affect all rows..."
[!WARNING] DELETE Safety: sqlo requires either a WHERE clause or explicit
.allow_all_rows()to prevent accidental mass deletions.
Delete All Rows (with confirmation)
# Delete ALL rows (requires explicit confirmation)
query = Q.delete_from("temp_logs").allow_all_rows()
sql, params = query.build()
# DELETE FROM `temp_logs`
Delete with WHERE
# Delete specific rows (recommended)
query = Q.delete_from("users").where("id", 123)
sql, params = query.build()
# DELETE FROM `users` WHERE `id` = %s
# Params: (123,)
WHERE Clause
Basic Conditions
# Single condition
query = Q.delete_from("users").where("active", False)
# Multiple AND conditions
query = (
Q.delete_from("logs")
.where("level", "debug")
.where("created_at <", "2023-01-01")
)
# DELETE FROM `logs` WHERE `level` = %s AND `created_at` < %s
OR Conditions
query = (
Q.delete_from("users")
.where("status", "banned")
.or_where("login_attempts >", 10)
)
# DELETE FROM `users` WHERE `status` = %s OR `login_attempts` > %s
IN Clause
query = Q.delete_from("users").where_in("id", [1, 2, 3, 4, 5])
# DELETE FROM `users` WHERE `id` IN (%s, %s, %s, %s, %s)
NULL Checks
# Delete rows with NULL values
query = Q.delete_from("tokens").where_null("expires_at")
# DELETE FROM `tokens` WHERE `expires_at` IS NULL
ORDER BY and LIMIT
Control which rows are deleted (useful for pruning):
# Delete oldest 100 logs
query = (
Q.delete_from("logs")
.order_by("created_at") # Ascending order (oldest first)
.limit(100)
)
# DELETE FROM `logs` ORDER BY `created_at` ASC LIMIT 100
# Delete newest records (e.g., undo recent imports)
query = (
Q.delete_from("imports")
.order_by("-created_at") # Descending order
.limit(10)
)
# DELETE FROM `imports` ORDER BY `created_at` DESC LIMIT 10
Advanced Usage
Multi-Table DELETE (MySQL)
Delete from multiple tables using JOINs:
# Delete users who have no orders
query = (
Q.delete_from("users")
.left_join("orders", "orders.user_id = users.id")
.where_null("orders.id")
)
# DELETE `users` FROM `users` LEFT JOIN `orders` ON orders.user_id = users.id WHERE `orders`.`id` IS NULL
DELETE with Subquery
# Delete users based on subquery
subquery = Q.select("user_id").from_("blacklisted_emails")
query = (
Q.delete_from("users")
.where_in("id", subquery)
)
# DELETE FROM `users` WHERE `id` IN (SELECT `user_id` FROM `blacklisted_emails`)
Safety Best Practices
1. Always Use WHERE
Never run Q.delete_from("table") without a WHERE clause unless you intentionally want to truncate the table.
2. Use Soft Deletes Instead
Consider using “Soft Deletes” (updating a deleted_at timestamp) instead of actual DELETE queries for important data.
# Instead of DELETE:
# query = Q.delete_from("users").where("id", 123)
# Use UPDATE:
query = (
Q.update("users")
.set({"deleted_at": "NOW()"})
.where("id", 123)
)
3. Limit Deletions
When running cleanup jobs, use limit() to avoid locking the table for too long.
# Delete in batches of 1000
query = (
Q.delete_from("logs")
.where("created_at <", "2022-01-01")
.limit(1000)
)
4. Verify Before Execution
def safe_delete(table_name, conditions):
if not conditions:
raise ValueError("Cannot delete without conditions!")
query = Q.delete_from(table_name)
for col, val in conditions.items():
query = query.where(col, val)
return query
Common Patterns
Pruning Old Data
from datetime import datetime, timedelta
# Delete logs older than 30 days
cutoff_date = datetime.now() - timedelta(days=30)
query = (
Q.delete_from("app_logs")
.where("created_at <", cutoff_date)
.limit(5000) # Limit batch size
)
Duplicate Removal
# Keep only the latest entry for each user_id (MySQL specific trick)
# This is complex and often better done with a temporary table or multiple queries
See Also
UPDATE Queries - Soft delete implementation
SELECT Queries - Selecting data to verify before delete
Condition Objects - Complex conditions