Reviews schema design, SQL queries, ORM patterns. Use when junior creates schema, writes queries, adds migrations, works with Prisma/MongoDB/PostgreSQL, or asks "is this SQL safe", "N+1", "index".
التثبيت
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
Reviews schema design, SQL queries, ORM patterns. Use when junior creates schema, writes queries, adds migrations, works with Prisma/MongoDB/PostgreSQL, or asks "is this SQL safe", "N+1", "index".
Database Fundamentals Review
"Your database is the foundation. Build it wrong, and everything above it will crack."
When to Apply
Activate this skill when reviewing:
Schema design and migrations
SQL/NoSQL queries
ORM model definitions
Data relationships
Index creation
Query performance
Review Checklist
Schema Design
Normalization: Is data normalized appropriately (no excessive duplication)?
Denormalization justified: If denormalized, is there a performance reason?
Primary keys: Does every table have a clear primary key?
Foreign keys: Are relationships enforced at the database level?
Data types: Are appropriate types used (not everything TEXT)?
Indexes
Query-based: Are indexes created for frequently queried columns?
Composite indexes: Are multi-column queries covered?
Not over-indexed: Are there unnecessary indexes slowing writes?
Unique constraints: Are unique fields enforced at DB level?
Queries
No N+1: Are related records fetched in bulk?
Select specific fields: Are we avoiding SELECT *?
Pagination: Do list queries limit results?
Parameterized: Are all queries parameterized (no string concatenation)?
Migrations
Reversible: Can this migration be rolled back?
No data loss: Will existing data survive the migration?
Tested: Has this been tested against production-like data?
Incremental: Are large changes broken into smaller migrations?
Common Mistakes (Anti-Patterns)
1. The N+1 Query Problem
❌ // 1 query for users + N queries for posts
const users = await User.findAll();
for (const user of users) {
user.posts = await Post.findAll({ where: { userId: user.id } });
}
✅ // 1 query with JOIN
const users = await User.findAll({
include: [{ model: Post }]
});
// Or 2 queries with IN clause
const users = await User.findAll();
const userIds = users.map(u => u.id);
const posts = await Post.findAll({ where: { userId: userIds } });
2. Missing Indexes
❌ // Queried frequently, but no index
SELECT * FROM orders WHERE user_id = ?
SELECT * FROM products WHERE category = ? AND status = 'active'
✅ CREATE INDEX idx_orders_user_id ON orders(user_id);
CREATE INDEX idx_products_category_status ON products(category, status);
3. SELECT * Everywhere
❌ SELECT * FROM users; // Returns 50 columns
✅ SELECT id, name, email FROM users; // Only what's needed
4. String Concatenation (SQL Injection)
❌ db.query(`SELECT * FROM users WHERE email = '${email}'`);
✅ db.query('SELECT * FROM users WHERE email = ?', [email]);
5. Destructive Migrations
❌ -- Can't be rolled back
DROP TABLE users;
ALTER TABLE orders DROP COLUMN status;
✅ -- Add new, migrate data, then drop old (in separate migrations)
-- Migration 1: Add new column
ALTER TABLE orders ADD COLUMN status_new VARCHAR(20);
-- Migration 2: Copy data
UPDATE orders SET status_new = status;
-- Migration 3: Drop old (after verification)
ALTER TABLE orders DROP COLUMN status;
Socratic Questions
Ask the junior these questions instead of giving answers:
Schema: "Why did you choose this data type?"
Relationships: "What happens if this related record is deleted?"
Indexes: "Which columns are queried together? Are they indexed?"
N+1: "How many queries does this operation execute?"
Migration: "What happens if we need to roll this back?"
Normalization Quick Reference
Form
Rule
Example Issue
1NF
No repeating groups
tags: "js,react,node" should be separate table
2NF
No partial dependencies
Order item price duplicated from products
3NF
No transitive dependencies
Storing city AND zip code (zip determines city)
When to Denormalize
Read-heavy workloads with rare writes
Calculated aggregates (e.g., order totals)
Caching frequently accessed derived data
Index Strategy
-- Single column (most common)CREATE INDEX idx_users_email ON users(email);
-- Composite (for multi-column queries)-- Order matters! Most selective firstCREATE INDEX idx_orders_user_date ON orders(user_id, created_at);
-- Partial (for filtered queries)CREATE INDEX idx_active_users ON users(email) WHERE active =true;
-- Unique (enforces constraint)CREATEUNIQUE INDEX idx_users_email_unique ON users(email);
Index Rules of Thumb
Index columns in WHERE clauses
Index columns in JOIN conditions
Index columns in ORDER BY (if used with WHERE)
Don't over-index write-heavy tables
Consider composite indexes for multi-column queries