[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-e0cb7611-74ca-4bd1-a6a8-83ae8b611634":3,"$fv8HPD9LYTR1ArCYXVftXXytaLe9BBrZfhadLgro5m_Y":42},{"id":4,"title":5,"description":6,"categoryId":7,"moduleId":8,"tags":9,"prompt":10,"icon":11,"source":12,"sourceUrl":13,"authorId":14,"authorName":15,"isPublic":16,"stars":17,"runs":18,"createdAt":19,"updatedAt":19,"module":20,"category":27,"packages":33},"e0cb7611-74ca-4bd1-a6a8-83ae8b611634","sql-database-assistant","使用时，当用户请求编写SQL查询、优化数据库性能、生成迁移、探索数据库模式或与Prisma、Drizzle、TypeORM或SQLAlchemy等ORM一起工作时。","cat_coding_backend","mod_coding","alirezarezvani,coding","---\nname: \"sql-database-assistant\"\ndescription: \"Use when the user asks to write SQL queries, optimize database performance, generate migrations, explore database schemas, or work with ORMs like Prisma, Drizzle, TypeORM, or SQLAlchemy.\"\n---\n\n# SQL Database Assistant - POWERFUL Tier Skill\n\n## Overview\n\nThe operational companion to database design. While **database-designer** focuses on schema architecture and **database-schema-designer** handles ERD modeling, this skill covers the day-to-day: writing queries, optimizing performance, generating migrations, and bridging the gap between application code and database engines.\n\n### Core Capabilities\n\n- **Natural Language to SQL** — translate requirements into correct, performant queries\n- **Schema Exploration** — introspect live databases across PostgreSQL, MySQL, SQLite, SQL Server\n- **Query Optimization** — EXPLAIN analysis, index recommendations, N+1 detection, rewrite patterns\n- **Migration Generation** — up\u002Fdown scripts, zero-downtime strategies, rollback plans\n- **ORM Integration** — Prisma, Drizzle, TypeORM, SQLAlchemy patterns and escape hatches\n- **Multi-Database Support** — dialect-aware SQL with compatibility guidance\n\n### Tools\n\n| Script | Purpose |\n|--------|---------|\n| `scripts\u002Fquery_optimizer.py` | Static analysis of SQL queries for performance issues |\n| `scripts\u002Fmigration_generator.py` | Generate migration file templates from change descriptions |\n| `scripts\u002Fschema_explorer.py` | Generate schema documentation from introspection queries |\n\n---\n\n## Natural Language to SQL\n\n### Translation Patterns\n\nWhen converting requirements to SQL, follow this sequence:\n\n1. **Identify entities** — map nouns to tables\n2. **Identify relationships** — map verbs to JOINs or subqueries\n3. **Identify filters** — map adjectives\u002Fconditions to WHERE clauses\n4. **Identify aggregations** — map \"total\", \"average\", \"count\" to GROUP BY\n5. **Identify ordering** — map \"top\", \"latest\", \"highest\" to ORDER BY + LIMIT\n\n### Common Query Templates\n\n**Top-N per group (window function)**\n```sql\nSELECT * FROM (\n  SELECT *, ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rn\n  FROM employees\n) ranked WHERE rn \u003C= 3;\n```\n\n**Running totals**\n```sql\nSELECT date, amount,\n  SUM(amount) OVER (ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS running_total\nFROM transactions;\n```\n\n**Gap detection**\n```sql\nSELECT curr.id, curr.seq_num, prev.seq_num AS prev_seq\nFROM records curr\nLEFT JOIN records prev ON prev.seq_num = curr.seq_num - 1\nWHERE prev.id IS NULL AND curr.seq_num > 1;\n```\n\n**UPSERT (PostgreSQL)**\n```sql\nINSERT INTO settings (key, value, updated_at)\nVALUES ('theme', 'dark', NOW())\nON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = EXCLUDED.updated_at;\n```\n\n**UPSERT (MySQL)**\n```sql\nINSERT INTO settings (key_name, value, updated_at)\nVALUES ('theme', 'dark', NOW())\nON DUPLICATE KEY UPDATE value = VALUES(value), updated_at = VALUES(updated_at);\n```\n\n> See references\u002Fquery_patterns.md for JOINs, CTEs, window functions, JSON operations, and more.\n\n---\n\n## Schema Exploration\n\n### Introspection Queries\n\n**PostgreSQL — list tables and columns**\n```sql\nSELECT table_name, column_name, data_type, is_nullable, column_default\nFROM information_schema.columns\nWHERE table_schema = 'public'\nORDER BY table_name, ordinal_position;\n```\n\n**PostgreSQL — foreign keys**\n```sql\nSELECT tc.table_name, kcu.column_name,\n  ccu.table_name AS foreign_table, ccu.column_name AS foreign_column\nFROM information_schema.table_constraints tc\nJOIN information_schema.key_column_usage kcu ON tc.constraint_name = kcu.constraint_name\nJOIN information_schema.constraint_column_usage ccu ON tc.constraint_name = ccu.constraint_name\nWHERE tc.constraint_type = 'FOREIGN KEY';\n```\n\n**MySQL — table sizes**\n```sql\nSELECT table_name, table_rows,\n  ROUND(data_length \u002F 1024 \u002F 1024, 2) AS data_mb,\n  ROUND(index_length \u002F 1024 \u002F 1024, 2) AS index_mb\nFROM information_schema.tables\nWHERE table_schema = DATABASE()\nORDER BY data_length DESC;\n```\n\n**SQLite — schema dump**\n```sql\nSELECT name, sql FROM sqlite_master WHERE type = 'table' ORDER BY name;\n```\n\n**SQL Server — columns with types**\n```sql\nSELECT t.name AS table_name, c.name AS column_name,\n  ty.name AS data_type, c.max_length, c.is_nullable\nFROM sys.columns c\nJOIN sys.tables t ON c.object_id = t.object_id\nJOIN sys.types ty ON c.user_type_id = ty.user_type_id\nORDER BY t.name, c.column_id;\n```\n\n### Generating Documentation from Schema\n\nUse `scripts\u002Fschema_explorer.py` to produce markdown or JSON documentation:\n\n```bash\npython scripts\u002Fschema_explorer.py --dialect postgres --tables all --format md\npython scripts\u002Fschema_explorer.py --dialect mysql --tables users,orders --format json --json\n```\n\n---\n\n## Query Optimization\n\n### EXPLAIN Analysis Workflow\n\n1. **Run EXPLAIN ANALYZE** (PostgreSQL) or **EXPLAIN FORMAT=JSON** (MySQL)\n2. **Identify the costliest node** — Seq Scan on large tables, Nested Loop with high row estimates\n3. **Check for missing indexes** — sequential scans on filtered columns\n4. **Look for estimation errors** — planned vs actual rows divergence signals stale statistics\n5. **Evaluate JOIN order** — ensure the smallest result set drives the join\n\n### Index Recommendation Checklist\n\n- Columns in WHERE clauses with high selectivity\n- Columns in JOIN conditions (foreign keys)\n- Columns in ORDER BY when combined with LIMIT\n- Composite indexes matching multi-column WHERE predicates (most selective column first)\n- Partial indexes for queries with constant filters (e.g., `WHERE status = 'active'`)\n- Covering indexes to avoid table lookups for read-heavy queries\n\n### Query Rewriting Patterns\n\n| Anti-Pattern | Rewrite |\n|-------------|---------|\n| `SELECT * FROM orders` | `SELECT id, status, total FROM orders` (explicit columns) |\n| `WHERE YEAR(created_at) = 2025` | `WHERE created_at >= '2025-01-01' AND created_at \u003C '2026-01-01'` (sargable) |\n| Correlated subquery in SELECT | LEFT JOIN with aggregation |\n| `NOT IN (SELECT ...)` with NULLs | `NOT EXISTS (SELECT 1 ...)` |\n| `UNION` (dedup) when not needed | `UNION ALL` |\n| `LIKE '%search%'` | Full-text search index (GIN\u002FFULLTEXT) |\n| `ORDER BY RAND()` | Application-side random sampling or `TABLESAMPLE` |\n\n### N+1 Detection\n\n**Symptoms:**\n- Application loop that executes one query per parent row\n- ORM lazy-loading related entities inside a loop\n- Query log shows hundreds of identical SELECT patterns with different IDs\n\n**Fixes:**\n- Use eager loading (`include` in Prisma, `joinedload` in SQLAlchemy)\n- Batch queries with `WHERE id IN (...)`\n- Use DataLoader pattern for GraphQL resolvers\n\n### Static Analysis Tool\n\n```bash\npython scripts\u002Fquery_optimizer.py --query \"SELECT * FROM orders WHERE status = 'pending'\" --dialect postgres\npython scripts\u002Fquery_optimizer.py --query queries.sql --dialect mysql --json\n```\n\n> See references\u002Foptimization_guide.md for EXPLAIN plan reading, index types, and connection pooling.\n\n---\n\n## Migration Generation\n\n### Zero-Downtime Migration Patterns\n\n**Adding a column (safe)**\n```sql\n-- Up\nALTER TABLE users ADD COLUMN phone VARCHAR(20);\n\n-- Down\nALTER TABLE users DROP COLUMN phone;\n```\n\n**Renaming a column (expand-contract)**\n```sql\n-- Step 1: Add new column\nALTER TABLE users ADD COLUMN full_name VARCHAR(255);\n-- Step 2: Backfill\nUPDATE users SET full_name = name;\n-- Step 3: Deploy app reading both columns\n-- Step 4: Deploy app writing only new column\n-- Step 5: Drop old column\nALTER TABLE users DROP COLUMN name;\n```\n\n**Adding a NOT NULL column (safe sequence)**\n```sql\n-- Step 1: Add nullable\nALTER TABLE orders ADD COLUMN region VARCHAR(50);\n-- Step 2: Backfill with default\nUPDATE orders SET region = 'unknown' WHERE region IS NULL;\n-- Step 3: Add constraint\nALTER TABLE orders ALTER COLUMN region SET NOT NULL;\nALTER TABLE orders ALTER COLUMN region SET DEFAULT 'unknown';\n```\n\n**Index creation (non-blocking, PostgreSQL)**\n```sql\nCREATE INDEX CONCURRENTLY idx_orders_status ON orders (status);\n```\n\n### Data Backfill Strategies\n\n- **Batch updates** — process in chunks of 1000-10000 rows to avoid lock contention\n- **Background jobs** — run backfills asynchronously with progress tracking\n- **Dual-write** — write to old and new columns during transition period\n- **Validation queries** — verify row counts and data integrity after each batch\n\n### Rollback Strategies\n\nEvery migration must have a reversible down script. For irreversible changes:\n\n1. **Backup before execution** — `pg_dump` the affected tables\n2. **Feature flags** — application can switch between old\u002Fnew schema reads\n3. **Shadow tables** — keep a copy of the original table during migration window\n\n### Migration Generator Tool\n\n```bash\npython scripts\u002Fmigration_generator.py --change \"add email_verified boolean to users\" --dialect postgres --format sql\npython scripts\u002Fmigration_generator.py --change \"rename column name to full_name in customers\" --dialect mysql --format alembic --json\n```\n\n---\n\n## Multi-Database Support\n\n### Dialect Differences\n\n| Feature | PostgreSQL | MySQL | SQLite | SQL Server |\n|---------|-----------|-------|--------|------------|\n| UPSERT | `ON CONFLICT DO UPDATE` | `ON DUPLICATE KEY UPDATE` | `ON CONFLICT DO UPDATE` | `MERGE` |\n| Boolean | Native `BOOLEAN` | `TINYINT(1)` | `INTEGER` | `BIT` |\n| Auto-increment | `SERIAL` \u002F `GENERATED` | `AUTO_INCREMENT` | `INTEGER PRIMARY KEY` | `IDENTITY` |\n| JSON | `JSONB` (indexed) | `JSON` | Text (ext) | `NVARCHAR(MAX)` |\n| Array | Native `ARRAY` | Not supported | Not supported | Not supported |\n| CTE (recursive) | Full support | 8.0+ | 3.8.3+ | Full support |\n| Window functions | Full support | 8.0+ | 3.25.0+ | Full support |\n| Full-text search | `tsvector` + GIN | `FULLTEXT` index | FTS5 extension | Full-text catalog |\n| LIMIT\u002FOFFSET | `LIMIT n OFFSET m` | `LIMIT n OFFSET m` | `LIMIT n OFFSET m` | `OFFSET m ROWS FETCH NEXT n ROWS ONLY` |\n\n### Compatibility Tips\n\n- **Always use parameterized queries** — prevents SQL injection across all dialects\n- **Avoid dialect-specific functions in shared code** — wrap in adapter layer\n- **Test migrations on target engine** — `information_schema` varies between engines\n- **Use ISO date format** — `'YYYY-MM-DD'` works everywhere\n- **Quote identifiers** — use double quotes (SQL standard) or backticks (MySQL)\n\n---\n\n## ORM Patterns\n\n### Prisma\n\n**Schema definition**\n```prisma\nmodel User {\n  id        Int      @id @default(autoincrement())\n  email     String   @unique\n  name      String?\n  posts     Post[]\n  createdAt DateTime @default(now())\n}\n\nmodel Post {\n  id       Int    @id @default(autoincrement())\n  title    String\n  author   User   @relation(fields: [authorId], references: [id])\n  authorId Int\n}\n```\n\n**Migrations**: `npx prisma migrate dev --name add_user_email`\n**Query API**: `prisma.user.findMany({ where: { email: { contains: '@' } }, include: { posts: true } })`\n**Raw SQL escape hatch**: `prisma.$queryRaw\\`SELECT * FROM users WHERE id = ${userId}\\``\n\n### Drizzle\n\n**Schema-first definition**\n```typescript\nexport const users = pgTable('users', {\n  id: serial('id').primaryKey(),\n  email: varchar('email', { length: 255 }).notNull().unique(),\n  name: text('name'),\n  createdAt: timestamp('created_at').defaultNow(),\n});\n```\n\n**Query builder**: `db.select().from(users).where(eq(users.email, email))`\n**Migrations**: `npx drizzle-kit generate:pg` then `npx drizzle-kit push:pg`\n\n### TypeORM\n\n**Entity decorators**\n```typescript\n@Entity()\nexport class User {\n  @PrimaryGeneratedColumn()\n  id: number;\n\n  @Column({ unique: true })\n  email: string;\n\n  @OneToMany(() => Post, post => post.author)\n  posts: Post[];\n}\n```\n\n**Repository pattern**: `userRepo.find({ where: { email }, relations: ['posts'] })`\n**Migrations**: `npx typeorm migration:generate -n AddUserEmail`\n\n### SQLAlchemy\n\n**Declarative models**\n```python\nclass User(Base):\n    __tablename__ = 'users'\n    id = Column(Integer, primary_key=True)\n    email = Column(String(255), unique=True, nullable=False)\n    name = Column(String(255))\n    posts = relationship('Post', back_populates='author')\n```\n\n**Session management**: Always use `with Session() as session:` context manager\n**Alembic migrations**: `alembic revision --autogenerate -m \"add user email\"`\n\n> See references\u002Form_patterns.md for side-by-side comparisons and migration workflows per ORM.\n\n---\n\n## Data Integrity\n\n### Constraint Strategy\n\n- **Primary keys** — every table must have one; prefer surrogate keys (serial\u002FUUID)\n- **Foreign keys** — enforce referential integrity; define ON DELETE behavior explicitly\n- **UNIQUE constraints** — for business-level uniqueness (email, slug, API key)\n- **CHECK constraints** — validate ranges, enums, and business rules at the DB level\n- **NOT NULL** — default to NOT NULL; make nullable only when genuinely optional\n\n### Transaction Isolation Levels\n\n| Level | Dirty Read | Non-Repeatable Read | Phantom Read | Use Case |\n|-------|-----------|-------------------|-------------|----------|\n| READ UNCOMMITTED | Yes | Yes | Yes | Never recommended |\n| READ COMMITTED | No | Yes | Yes | Default for PostgreSQL, general OLTP |\n| REPEATABLE READ | No | No | Yes (InnoDB: No) | Financial calculations |\n| SERIALIZABLE | No | No | No | Critical consistency (billing, inventory) |\n\n### Deadlock Prevention\n\n1. **Consistent lock ordering** — always acquire locks in the same table\u002Frow order\n2. **Short transactions** — minimize time between first lock and commit\n3. **Advisory locks** — use `pg_advisory_lock()` for application-level coordination\n4. **Retry logic** — catch deadlock errors and retry with exponential backoff\n\n---\n\n## Backup & Restore\n\n### PostgreSQL\n```bash\n# Full backup\npg_dump -Fc --no-owner dbname > backup.dump\n# Restore\npg_restore -d dbname --clean --no-owner backup.dump\n# Point-in-time recovery: configure WAL archiving + restore_command\n```\n\n### MySQL\n```bash\n# Full backup\nmysqldump --single-transaction --routines --triggers dbname > backup.sql\n# Restore\nmysql dbname \u003C backup.sql\n# Binary log for PITR: mysqlbinlog --start-datetime=\"2025-01-01 00:00:00\" binlog.000001\n```\n\n### SQLite\n```bash\n# Backup (safe with concurrent reads)\nsqlite3 dbname \".backup backup.db\"\n```\n\n### Backup Best Practices\n- **Automate** — cron or systemd timer, never manual-only\n- **Test restores** — untested backups are not backups\n- **Offsite copies** — S3, GCS, or separate region\n- **Retention policy** — daily for 7 days, weekly for 4 weeks, monthly for 12 months\n- **Monitor backup size and duration** — sudden changes signal issues\n\n---\n\n## Anti-Patterns\n\n| Anti-Pattern | Problem | Fix |\n|-------------|---------|-----|\n| `SELECT *` | Transfers unnecessary data, breaks on schema changes | Explicit column list |\n| Missing indexes on FK columns | Slow JOINs and cascading deletes | Add indexes on all foreign keys |\n| N+1 queries | 1 + N round trips to database | Eager loading or batch queries |\n| Implicit type coercion | `WHERE id = '123'` prevents index use | Match types in predicates |\n| No connection pooling | Exhausts connections under load | PgBouncer, ProxySQL, or ORM pool |\n| Unbounded queries | No LIMIT risks returning millions of rows | Always paginate |\n| Storing money as FLOAT | Rounding errors | Use `DECIMAL(19,4)` or integer cents |\n| God tables | One table with 50+ columns | Normalize or use vertical partitioning |\n| Soft deletes everywhere | Complicates every query with `WHERE deleted_at IS NULL` | Archive tables or event sourcing |\n| Raw string concatenation | SQL injection | Parameterized queries always |\n\n---\n\n## Cross-References\n\n| Skill | Relationship |\n|-------|-------------|\n| **database-designer** | Schema architecture, normalization analysis, ERD generation |\n| **database-schema-designer** | Visual ERD modeling, relationship mapping |\n| **migration-architect** | Complex multi-step migration orchestration |\n| **api-design-reviewer** | Ensuring API endpoints align with query patterns |\n| **observability-platform** | Query performance monitoring, slow query alerts |\n","","imported","https:\u002F\u002Fgithub.com\u002Falirezarezvani\u002Fclaude-skills","user_system_seed","SkillOPIC",true,198,560,"2026-05-16 13:55:38",{"id":8,"name":21,"slug":22,"icon":23,"description":24,"sort":25,"createdAt":26},"编程开发","coding","mdi-code-braces","代码生成、调试、审查，提升开发效率",2,"2026-05-16 12:53:40",{"id":7,"name":28,"slug":29,"icon":30,"description":31,"moduleId":8,"sort":25,"skillCount":32,"createdAt":26},"后端开发","backend","mdi-server","API、数据库、服务端架构",296,[34],{"id":35,"skillId":4,"version":36,"fileName":37,"fileSize":38,"filePath":39,"fileHash":40,"manifest":41,"createdAt":19},"3f7c12f5-b57d-480e-b959-c8b9d62fedeb","1.0.0","sql-database-assistant.zip",31028,"uploads\u002Fskills\u002Fe0cb7611-74ca-4bd1-a6a8-83ae8b611634\u002Fsql-database-assistant.zip","90484b2c570f27d1f56dc94804897e5ddedb643a30a88f6c1d778b246342bd9c","[{\"path\":\"SKILL.md\",\"isDirectory\":false,\"size\":16077},{\"path\":\"references\u002Foptimization_guide.md\",\"isDirectory\":false,\"size\":10699},{\"path\":\"references\u002Form_patterns.md\",\"isDirectory\":false,\"size\":12565},{\"path\":\"references\u002Fquery_patterns.md\",\"isDirectory\":false,\"size\":9787},{\"path\":\"scripts\u002Fmigration_generator.py\",\"isDirectory\":false,\"size\":16436},{\"path\":\"scripts\u002Fquery_optimizer.py\",\"isDirectory\":false,\"size\":11756},{\"path\":\"scripts\u002Fschema_explorer.py\",\"isDirectory\":false,\"size\":14300}]",{"code":43,"message":44,"data":45},200,"success",{"items":46,"stats":47,"page":50},[],{"averageRating":48,"totalRatings":48,"ratingCounts":49},0,[48,48,48,48,48],{"limit":51,"offset":48,"hasMore":52,"nextOffset":51,"ratedOnly":16},15,false]