Database Operations
Safe database interaction patterns including SQL query construction, migration writing, transaction handling, and read/write operation safety.
You are an autonomous agent that interacts with databases safely and effectively. You treat every database operation as potentially destructive, you never construct queries from unvalidated input, and you understand that data integrity is paramount. ## Key Points - **Never concatenate user input into SQL strings.** Always use parameterized queries or prepared statements. This is the single most important rule for database safety. - Bad: `"SELECT * FROM users WHERE id = " + userId` - Good: `"SELECT * FROM users WHERE id = $1"` with `[userId]` as parameter. - Use `SELECT` with explicit column names instead of `SELECT *`. This documents intent and prevents unexpected column additions from breaking code. - `LIMIT` your queries, especially during exploration. An unbounded `SELECT` on a large table can exhaust memory or block other operations. - Use `EXPLAIN` or `EXPLAIN ANALYZE` to understand query performance before running expensive queries in production. - Migrations should be idempotent where possible. Use `IF NOT EXISTS` for creating tables and columns. - Every migration should have an `up` and a `down` (rollback). Test both directions. - Never modify a migration that has already been applied to shared environments. Create a new migration instead. - Name migrations descriptively: `20240115_add_email_index_to_users` not `migration_47`. - Migrations that modify large tables (adding columns, creating indexes) can lock the table. Use `CONCURRENTLY` options where available or schedule during low-traffic periods. - Data migrations (transforming existing data) should be separate from schema migrations (changing table structure).
skilldb get autonomous-agent-skills/database-operationsFull skill: 87 linesDatabase Operations
You are an autonomous agent that interacts with databases safely and effectively. You treat every database operation as potentially destructive, you never construct queries from unvalidated input, and you understand that data integrity is paramount.
Philosophy
Databases are the source of truth for applications. A bad query can corrupt data, expose sensitive information, or take down a production system. Every database interaction must be deliberate, safe, and reversible where possible. Read operations should be efficient. Write operations should be transactional. Destructive operations should require explicit confirmation and have rollback plans.
Techniques
SQL Query Construction
- Never concatenate user input into SQL strings. Always use parameterized queries or prepared statements. This is the single most important rule for database safety.
- Bad:
"SELECT * FROM users WHERE id = " + userId - Good:
"SELECT * FROM users WHERE id = $1"with[userId]as parameter. - Use
SELECTwith explicit column names instead ofSELECT *. This documents intent and prevents unexpected column additions from breaking code. LIMITyour queries, especially during exploration. An unboundedSELECTon a large table can exhaust memory or block other operations.- Use
EXPLAINorEXPLAIN ANALYZEto understand query performance before running expensive queries in production.
Migration Writing
- Migrations should be idempotent where possible. Use
IF NOT EXISTSfor creating tables and columns. - Every migration should have an
upand adown(rollback). Test both directions. - Never modify a migration that has already been applied to shared environments. Create a new migration instead.
- Name migrations descriptively:
20240115_add_email_index_to_usersnotmigration_47. - Migrations that modify large tables (adding columns, creating indexes) can lock the table. Use
CONCURRENTLYoptions where available or schedule during low-traffic periods. - Data migrations (transforming existing data) should be separate from schema migrations (changing table structure).
Schema Understanding
- Before writing queries, understand the schema. Check table definitions, column types, indexes, constraints, and foreign keys.
INFORMATION_SCHEMAor tool-specific commands (\dtin psql,.tablesin sqlite3,SHOW TABLESin MySQL) reveal structure.- Pay attention to nullable columns — they change query semantics.
WHERE status != 'active'does not match rows wherestatus IS NULL. - Understand primary keys and unique constraints. They define what makes a record unique and affect upsert behavior.
Transaction Handling
- Wrap related write operations in transactions. Either all changes succeed or none do.
- Keep transactions short. Long-running transactions hold locks and block other operations.
- Use appropriate isolation levels.
READ COMMITTEDis the default and sufficient for most operations.SERIALIZABLEprevents more anomalies but reduces concurrency. - Always handle transaction errors: catch exceptions and explicitly
ROLLBACKto release locks. - Nested transactions are typically implemented via savepoints. Understand how your database handles them.
Connection Management
- Use connection pools in application code. Opening a new connection per query is expensive.
- Close connections when done. Connection leaks eventually exhaust the database's connection limit.
- Set reasonable timeouts for queries. A runaway query should not block the connection pool indefinitely.
- Distinguish between read and write connections when using read replicas. Never send writes to a read replica.
Query Optimization
- Index columns that appear in
WHERE,JOIN,ORDER BY, andGROUP BYclauses. - Avoid
SELECT *in production queries. Fetch only needed columns. - Use
EXISTSinstead ofCOUNT(*)when checking for existence. - Avoid functions on indexed columns in
WHEREclauses:WHERE LOWER(email) = 'x'cannot use an index onemail(use a functional index or store normalized data). - N+1 query problems: if you are running one query per item in a loop, refactor to a single query with
INorJOIN.
Read vs Write Safety
- Read operations are generally safe but can still cause problems: full table scans, lock contention on busy tables, or exposing sensitive data.
- Write operations (
INSERT,UPDATE,DELETE) should always include aWHEREclause. AnUPDATEwithoutWHEREmodifies every row. - Before running a
DELETEorUPDATE, run the equivalentSELECTwith the sameWHEREclause to verify which rows will be affected. TRUNCATEis faster thanDELETEfor clearing tables but cannot be rolled back in some databases and does not fire triggers.
Best Practices
- Back up before destructive operations. Before running mass updates, deletions, or migrations on production data, ensure a recent backup exists.
- Use soft deletes when appropriate. Set a
deleted_attimestamp instead of removing rows. This allows recovery and audit trails. - Test queries on staging first. Run any non-trivial query against a staging environment before production.
- Log all write operations. Maintain an audit trail of who changed what and when.
- Use database constraints.
NOT NULL,UNIQUE,FOREIGN KEY, andCHECKconstraints catch bugs at the database level. - Prefer ORM-generated queries for standard operations. Hand-written SQL for complex queries. Know when each approach is appropriate.
Anti-Patterns
- String concatenation for queries. The number one cause of SQL injection vulnerabilities. Use parameterized queries always.
- Running migrations without reviewing them. Auto-generated migrations may contain unexpected destructive changes.
- Missing WHERE on UPDATE/DELETE. This is how entire tables get wiped. Always verify the WHERE clause.
- Ignoring query performance. A query that works fine on 100 rows may take minutes on 10 million rows.
- Storing secrets in the database unencrypted. Passwords should be hashed. API keys and tokens should be encrypted at rest.
- Using the database as a queue. Polling a table for new rows is inefficient. Use a proper message queue for async work.
Install this skill directly: skilldb add autonomous-agent-skills
Related Skills
Dead Code Cleanup
Identifying and safely removing dead code during modifications without breaking hidden dependencies or dynamic references
Debugging Strategies
Systematic approaches to finding and fixing bugs — hypothesis-driven debugging, bisection, stack trace reading, issue reproduction, variable isolation, log analysis, and avoiding shotgun debugging.
Dependency Analysis
Understanding and managing project dependencies — reading manifest files, version conflict resolution, transitive dependency awareness, security audits, minimal dependency philosophy, and lock file handling.
Dependency Injection Patterns
Understanding and implementing dependency injection — constructor injection, DI containers, inversion of control, and knowing when DI adds value vs when it is over-engineering.
DNS and Networking Basics
Networking fundamentals for development including DNS, HTTP/HTTPS, TCP/UDP, CORS, SSL/TLS, load balancing, reverse proxies, and network debugging techniques.
Docker Container Management
Working with Docker for development and deployment, including Dockerfile best practices, compose patterns, image optimization, and container debugging.