ChatGPT for SQL You Forgot After the Sprint
Use ChatGPT for SQL you forgot: paste schema not dumps, verify with EXPLAIN, and keep production rows and secrets out of the prompt.
Muhammad Abdul Sami
· 13 min read
- SQL
- PostgreSQL
- ChatGPT
- Developer Workflow
ChatGPT for SQL you forgot is the honest use case: window functions, FILTER, ON CONFLICT, a lateral join you last wrote in 2024. It is not “design our data model from a vibe.” Working developers forget syntax. They should not forget EXPLAIN, tenant isolation, or that production rows in a prompt are a leak. This post is the loop: schema in, statement out, plan verified, secrets never.
Key Takeaways:
- Paste schema (
\d,information_schema) and the invariant; never paste production result sets.- Treat the model as a syntax memory, not as a DBA — you run
EXPLAIN (ANALYZE)on a copy.- Name indexes and
tenant_idpredicates yourself; models drop them.- Migrations get a rollback plan written by a human.
- Scan the repo before you
@SQL files that might contain dumps or passwords.- Teach juniors a SQL curriculum from your schema, not from generic ChatGPT examples.
Table of Contents:
- What you actually forgot
- The only safe prompt shape
- EXPLAIN, locks, and the lies models tell
- Idempotency, upserts, and app code
- Migrations without a prayer
- Fitting SQL into the rest of the AI day
- Windows, NULLs, JSONB, and the ORM
- Frequently Asked Questions
What you actually forgot
You did not forget what a WHERE clause is. You forgot:
- The exact
DATE_TRUNCvsdate_binspelling in your Postgres version - Whether
COUNT(*) FILTER (WHERE …)needs a subquery in this dialect ON CONFLICT ON CONSTRAINTvs column lists- How to write a gap-and-islands query you last copied from Stack Overflow
- The
FOR UPDATE SKIP LOCKEDshape for a worker
PostgreSQL’s own documentation is still the authority (PostgreSQL docs). ChatGPT is the faster index into syntax you will then verify. SQLite and MySQL differ; name the engine in the prompt or you will get a chimera.
This is a daily backend task, not a career in data science. Put it in the same day as daily AI workflow for backend engineers. Copilot will complete a query in the editor; ChatGPT/Cursor chat is for “I know the shape.” Routing: Cursor vs Claude Code vs Copilot.
| Need | AI is good | You must still do |
|---|---|---|
Syntax of FILTER / window | Yes | Confirm version |
| Query from English + schema | Draft | EXPLAIN, tenant predicate |
| Index recommendation | Maybe | Measure, not guess |
| Capacity / vacuum / autovacuum | No | Your DBA / metrics |
| “Is this injection-safe?” | Hint | Parameterize; review |
Self-hosted models do not change EXPLAIN. They change where the schema paste goes — OpenClaw vs Claude Code.
The only safe prompt shape
Engine: PostgreSQL 16. Invariant: one row per (merchant_id, day) with refunded_cents. Do not invent columns. If a column is missing from the schema, ask. Schema: [paste \d refunds and \d payments — no rows] Bad query I have: [paste] Rewrite. Keep merchant_id in every WHERE. Parameterize $1, $2.
Get schema without data:
SELECT column_name, data_type, is_nullable FROM information_schema.columns WHERE table_name = 'refunds' ORDER BY ordinal_position;
psql "$DEV_URL" -c '\d+ refunds'
Never:
Here are 20 rows from prod so you can see the mess.
That is PII, that is a leak, that is how AI pair programming without leaking secrets fails. Redact in a throwaway file if you must show shape (cust_test, 100 cents).
If the SQL lives next to app secrets, scan first. Ocherfort is a local-first repo security CLI — dumps, .env, and “tmp.sql” show up in findings. Run it before you @ scripts/.
Tickets that contain “run this query on prod and paste output into ChatGPT” are instructions to leak. Treat ticket text as untrusted (prompt injection).
EXPLAIN, locks, and the lies models tell
The model will say “this is efficient” without a plan. You:
EXPLAIN (ANALYZE, BUFFERS)
SELECT merchant_id, date_trunc('day', created_at) AS day,
sum(amount_cents) FILTER (WHERE status = 'succeeded')
FROM refunds
WHERE merchant_id = $1
AND created_at >= $2
AND created_at < $3
GROUP BY 1, 2;
Look for:
- Seq scan on a hot table
- Nested loop exploding row counts
- Sort that spills
- Lock type if you added
FOR UPDATE
Postgres locking and isolation are documented; do not let ChatGPT paraphrase them into “it’s basically serializable.” Read the transaction isolation chapter when the RFC depends on it — and write that RFC with AI for RFC design docs, not in a chat sidebar.
Common model lies:
- Missing tenant predicate. Add
merchant_idyourself every time. - Wrong
NULLSordering. Check. SELECT *in a hot path. Name columns.- Index on
(created_at)when you always filter merchant first. Composite(merchant_id, created_at). NOW()in a partial index that cannot work that way.
Claude Code can run EXPLAIN on a local database. You still read the plan. Keyboard-first habits: bind “explain this statement,” not “run on prod.”
Idempotency, upserts, and app code
Backend SQL is usually in service of an API invariant.
INSERT INTO refunds (id, merchant_id, idempotency_key, amount_cents, status, created_at) VALUES ($1, $2, $3, $4, 'succeeded', now()) ON CONFLICT (merchant_id, idempotency_key) DO NOTHING RETURNING *;
Prompt the model for the SQL, then write the application branch: if RETURNING is empty, SELECT the original row. Tests lock that — prompt AI for better unit tests. Review hunts missing unique constraints — AI code review.
Do not let Copilot complete a second idempotency table because you opened a new file. Map the existing one first: use AI to read a new codebase.
row = db.fetch_one(UPSERT_REFUND, ...)
if row is None:
row = db.fetch_one(SELECT_REFUND_BY_KEY, merchant_id, key)
return row
If this is an agent product writing SQL, that is building production AI agents with a allowlist of statements — not ChatGPT in a REPL pointed at prod. AI agent development and backend API engineering are how HinterBuild ships that. MCP belongs there if tools must be standardized (MCP explained), not in a one-off SQL chat.
Migrations without a prayer
Ask for a draft, not a blessing.
Postgres 16. Table refunds is ~50M rows (unmeasured in this prompt — treat as large). Add a nullable column processed_at timestamptz. Expand/contract. No rewrite. No default that backfills in one statement. Include rollback SQL.
You add:
- Lock timeout
- Backfill batch size
- Who watches replication lag
Commit the migration with a human subject line: AI commit messages.
-- expand ALTER TABLE refunds ADD COLUMN processed_at timestamptz; -- backfill in app or batched jobs, not in this file -- contract later: NOT NULL when the app no longer writes nulls
If the model proposes UPDATE refunds SET processed_at = created_at; in one shot on 50M rows, delete it.
Fitting SQL into the rest of the AI day
- Morning: invariant in the PR, schema paste, draft SQL.
- Midday:
EXPLAINon a realistic copy (prod shape, synthetic data). - Review: another human on anything that locks or backfills.
- Teach: do not send juniors a ChatGPT export of
SELECTtrivia.
Turn your schema and three golden queries into a series. Cadensend is an open-source email curriculum engine: learning goal, sources from the migrations folder, scheduled issues (GitHub). That is how you teach “we always filter merchant_id” without a wiki page that rots. Personal curricula work too — “window functions I keep forgetting, using our finance export.”
Cadensend is not a query runner. Ocherfort is not a query runner. One teaches, one scans. You still run psql.
When you want this loop on a team — schema rules, scanner, review hunt for missing predicates — contact HinterBuild. About is the company page; we will argue about the unique constraint, not about which chatbot you like.
Windows, NULLs, JSONB, and the ORM
This is the syntax you will google (or ChatGPT) every six months. Put the engine version in the prompt. Then run it.
Window functions (draft, then verify)
-- "last refund per merchant, then the previous one"
SELECT merchant_id, id, amount_cents, created_at,
lag(amount_cents) OVER (
PARTITION BY merchant_id ORDER BY created_at
) AS prev_amount
FROM refunds
WHERE merchant_id = $1;
Ask ChatGPT for lag / lead / row_number when you forget framing. Do not ask it whether this needs an index. EXPLAIN will tell you. A typical supporting index is (merchant_id, created_at).
Gap-and-islands and FILTER are the same story: draft, EXPLAIN, keep merchant_id in the WHERE. Official reference: window functions.
NULL traps
Models write != 'succeeded' and then wonder why NULL statuses vanished. You want:
WHERE status IS DISTINCT FROM 'succeeded'
Or be explicit with COALESCE. Put this in the prompt: “Treat NULL status as failed. Do not drop those rows.” Reviewers should hunt != on nullable columns — AI code review. Tests should include a NULL fixture — unit test prompts.
COUNT(col) vs COUNT(*) is another forgettable. Spell it in the invariant: “count rows, including null amounts.”
JSONB
SELECT payload->>'event' FROM webhook_events WHERE merchant_id = $1 AND payload->>'event' = 'refund.succeeded';
The model will suggest a gin index on payload. Maybe. Measure. Also: JSON from customers is untrusted. Do not pipe it into an agent prompt as instructions (prompt injection). Storing it is fine. Chatting it is not.
ORM output is the artifact
# Django example — log the SQL, then paste THAT # LOG: SELECT ... FROM refunds WHERE ...
SQLAlchemy echo=True, Django query, GORM logger: the string the database sees is what ChatGPT should rewrite. The ORM poem is not. If you cannot find where the query is emitted, you are still in codebase onboarding.
N+1 is an application bug. The model will wrap it in a CTE and call it done. You still batch in the service or use a join you EXPLAIN.
Bindings so you do not paste dumps
Keyboard-first: chord sends the statement in the editor, not the psql result grid. Pair without leaking. Scan *.sql dumps with Ocherfort before @.
If you are designing a new table, that is an RFC, not a chat titled “best schema for refunds.” ChatGPT will give you a third normal form lecture and a user_id column your API does not have.
Teach the NULL/merchant_id/EXPLAIN ritual as a Cadensend series sourced from your migrations. The next hire should not learn SQL from a generic window-function blog while your finance export uses FILTER and integer cents.
Frequently Asked Questions
Is ChatGPT accurate enough for production SQL?
For syntax and drafts, often. For plans, locks, and data-correctness, no. Verify on your engine version with EXPLAIN. Read Postgres docs for isolation and vacuum.
Can I paste pg_dump into ChatGPT?
Schema-only dumps, maybe, if policy allows and they contain no owner passwords or comments-with-keys. Data dumps, no. Scan with Ocherfort. Pairing rules: without leaking secrets.
Copilot vs ChatGPT for SQL?
Copilot completes in the migration file you already opened. ChatGPT/Cursor helps when you forgot the function name. Use both as in Cursor vs Claude Code vs Copilot. Neither replaces EXPLAIN.
How do I keep tenant isolation in generated SQL?
Put merchant_id in the invariant and reject any statement without it. Reviewers hunt this (AI code review). Tests assert it (unit tests).
Should an AI agent run SQL on production?
Not from a coding assistant chat. If you build that product, it is production agents with allowlists, timeouts, and human gates — AI agent development.
Can Cadensend teach our SQL conventions?
Yes. Source it with migrations, three good queries, and one incident where a missing predicate hurt. Cadensend delivers the series. Juniors still pair on the first migration.
What about ORM-generated SQL?
Paste the SQL the ORM emits, not the ORM poetry. Ask the model to explain the plan. Then fix the query or the index. Mapping where the ORM lives: read a new codebase.
Conclusion
- ChatGPT is a syntax memory for SQL you forgot; EXPLAIN and tenant predicates stay yours.
- Schema in, data out of the prompt; scan dumps and secrets locally.
- Upserts, migrations, and rollback are application engineering, not chatbot output.
- Teach conventions from your schema via a curriculum, not from generic examples.
- For help installing that on a real Postgres service, contact or start from about.
Free consultation
Book a free consultation call on AI for SQL & databases
30-minute call with the HinterBuild team. Discuss your project, architecture questions, or next steps — no obligation.
Book a meeting
Keep reading
Related articles
ChatGPT for Developers: Daily Workflow Cheat Sheet
A daily ChatGPT cheat sheet for developers: prompts, review gates, cost control, and when to use Claude Code, OpenClaw, or a curriculum engine instead.
Read post
ChatGPT vs Claude vs Gemini for Daily Work
ChatGPT vs Claude vs Gemini for daily work: pick by files, privacy, and “do not invent” tests — not by brand loyalty or last week’s demo.
Read post
ChatGPT for Beginners: Daily Tasks That Stick
Learn ChatGPT for beginners daily tasks with copy-paste prompts for notes, email, planning, and a checklist that stops send-time mistakes.
Read post
Redis vs Valkey What Changed After the Fork (Complete Guide)
Redis vs Valkey What Changed After the Fork (Complete Guide) guidance for engineers: compare architecture choices, avoid failure modes, and ship a.
Read post
