Data & APIs

SQL Review

Review a hand-written query for correctness first -- does it actually compute what the author thinks -- then for the index/plan implications.

When to use this

  • A new or changed hand-written SQL query (report, migration, application query) needs review.
  • Reviewing a complex query with joins/aggregations for logical correctness, not just style.
  • Not for interpreting a slow query's execution plan -- use query-optimizer for that; this is about logical correctness first.

The skill file

Copy this verbatim. It's written in the SKILL.md format (YAML frontmatter + markdown instructions) that Claude Code, and increasingly other agent tools, read directly.

SKILL.md
---
name: sql-review
description: Review a hand-written SQL query for logical correctness -- join conditions, NULL handling, aggregation grouping, edge cases -- before considering performance. Use for new or changed queries, especially ones with joins or aggregation.
---

# SQL Review

Correctness first. A fast query that returns the wrong answer is worse
than a slow one that's right.

## Correctness checklist

- **Join conditions**: does every join key actually mean what it should?
  A join that's missing a condition (accidentally producing a cross
  join / row multiplication) is the single most common serious SQL bug --
  check the row count sanity, not just the syntax.
- **NULL handling**: does a `WHERE column != value` accidentally exclude
  rows where `column IS NULL` (it does, in standard SQL, silently)? Does
  an aggregate function's NULL-skipping behavior match what the author
  intended?
- **Aggregation and GROUP BY**: does the GROUP BY clause include every
  non-aggregated selected column (or does the dialect silently allow
  it and produce an arbitrary value)? Does a HAVING clause filter on the
  aggregate correctly, not accidentally duplicating WHERE logic that
  should run before grouping?
- **Row multiplication from joins**: when joining a one-to-many
  relationship before aggregating, are counts/sums inflated by the join
  fan-out? (Classic bug: `SUM(order.amount)` after joining orders to
  order_items multiplies the order amount by the item count.)
- **Date/time boundaries**: off-by-one on date ranges (`<` vs `<=` on an
  end date), timezone assumptions, and whether a "between two dates"
  filter correctly includes/excludes boundary timestamps.

## Then performance

Once correctness is confirmed, check for the query-optimizer concerns
(index usage, plan shape) as a separate pass.

## Output

Correctness findings first (each with the specific rows/scenario that
would be wrong), performance notes second, clearly separated.

Installing it elsewhere

The frontmatter/body split above is Claude Code's convention. Here's how to carry the same instructions into other tools:

Claude Code
.claude/skills/sql-review/SKILL.md

Save the file below verbatim (frontmatter included) at that path, project-local or in ~/.claude/skills/ for a user-level skill. Claude Code loads the name/description pair to decide when to pull it in, or you invoke it directly as /sql-review.

Cursor
.cursor/rules/sql-review.mdc

Convert the YAML frontmatter to Cursor's rule format (description, globs, alwaysApply: false) and keep the markdown body as the rule content. Cursor surfaces it by description match, same idea as Claude Code's auto-load.

Codex CLI / Copilot
AGENTS.md

Codex CLI (and increasingly other agentic CLIs) read AGENTS.md at the repo root as always-on instructions. Paste the markdown body under a heading like ## {title}; for GitHub Copilot's coding agent, the equivalent file is .github/copilot-instructions.md.

Windsurf
.windsurfrules

Append the markdown body to .windsurfrules at the repo root. Windsurf treats the whole file as always-on context, so keep only the instructions you want applied on every request.

Where this goes wrong
  • Reviewing only for style/formatting and missing a join that silently multiplies rows before an aggregation.
  • Missing that `!= value` excludes NULL rows when the author intended to include them.
  • Checking performance before confirming the query is even logically correct.