Tinker AI
Read reviews
intermediate 7 min read

AI-assisted SQL: when it speeds you up and when it'll break your data

Published 2026-03-22 by Owner

SQL is one of the places AI tools are simultaneously most useful and most dangerous. Useful because the syntax is well-documented and patterns are common. Dangerous because a SQL query that looks right and works on small data can destroy your production database when it hits real volumes — and the AI has no way to know.

This guide is the workflow I’ve landed on for using AI tools (Cursor, Copilot, Cline) for SQL work, after a year of doing this on production-scale Postgres and a few close calls.

The fundamental rule

The AI doesn’t know your data. It knows SQL syntax, common patterns, and what your schema looks like if you’ve shown it. It does not know:

  • How big your tables are
  • What your indexes are
  • Which queries are hot paths in production
  • What locks your database is currently holding
  • The blast radius of a DELETE or UPDATE if it doesn’t go as expected

Every AI-generated SQL must be evaluated against these things. The AI doesn’t do this evaluation. You do.

The setup that helps

Three things to set up before asking AI for SQL help:

1. Show it your schema

If your project has a schema dump, an ORM model file, or a migration history, attach it to the prompt. Without this, the AI infers your schema from the immediate context, which is often wrong in non-obvious ways.

For Postgres, a useful schema dump:

pg_dump --schema-only --no-owner --no-acl mydb > schema.sql

Drop this in your repo (or a sibling docs folder) and reference it when asking SQL questions. Cursor’s @schema.sql reads it as context.

2. Set up a read-only connection for testing

For interactive SQL work, AI suggestions should be runnable against a read-only context first:

  • Read replica with read-only credentials
  • Local dump of production data
  • Sample database that mirrors production schema

If your only option is “run the AI’s suggestion against prod,” your setup is wrong before any AI is involved. Get a read-only path first.

3. Have an EXPLAIN habit

The single most useful command for evaluating AI-generated SQL is EXPLAIN ANALYZE. Run it on every non-trivial query the AI produces, against representative data, before you trust it.

EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM users
WHERE created_at > NOW() - INTERVAL '7 days'
  AND organization_id = 42;

The output tells you: which indexes were used, how many rows were scanned, whether there’s a sequential scan that shouldn’t be. This is the verification step that catches the most common AI failure mode.

The categories of SQL where AI is genuinely useful

After tracking my own use for a few months:

Generating boilerplate joins — multi-table SELECTs where the joins are obvious from foreign keys. AI gets these right almost always, and they’re tedious to type.

Translating between query forms — converting a subquery to a JOIN, a CASE expression to a FILTER clause, an OR to a UNION. AI handles these well because the patterns are equivalences, and equivalences are well-represented in training data.

Writing migration SQL — adding a column, creating an index, renaming a thing. The AI knows the syntax variations across PG/MySQL/SQLite better than I do.

Generating test data — INSERT statements with realistic-looking values for development. Useful for quickly seeding a test environment.

Documentation generation — comments on tables and columns. Boring but valuable; AI does it well.

These five categories are where SQL-with-AI feels like a real productivity gain. The risk is low because either the queries are simple (boilerplate), or they’re being checked at low stakes (test data, documentation).

The categories where AI is dangerous

Aggregations on large tables. AI will write SELECT COUNT(*) FROM big_table WHERE messy_condition and not know that this query requires a sequential scan of 200M rows. The query is syntactically correct. It’s also a 90-second outage if you run it on the wrong replica.

The check: always EXPLAIN before running. If you see Seq Scan on big_table, stop and think. There’s almost always an index pattern that turns this into something fast, and the AI didn’t know to use it.

JOINs with implicit cardinality assumptions. AI sometimes writes joins assuming a one-to-one relationship that’s actually one-to-many. The query returns more rows than expected, sometimes silently — your aggregations are now wrong.

The check: count the rows the join produces, check against your expected cardinality, and run a LEFT JOIN instead of INNER JOIN if you suspect missing matches.

Index-affecting queries. AI will sometimes write a WHERE clause that prevents the planner from using your index. Common culprits: function calls on indexed columns (WHERE LOWER(email) = ...), implicit type casts, ORs across columns.

The check: EXPLAIN, look for the index you expected, rewrite if it’s not there.

Bulk UPDATEs and DELETEs. This is the highest-risk category. An AI-generated UPDATE users SET ... WHERE ... that looks right and has a subtle WHERE clause bug will do unbounded damage. The damage is hard to undo.

The discipline: never run a UPDATE or DELETE the AI generated. Convert it to a SELECT first, run that, verify the rows are what you expect. Then convert back to UPDATE/DELETE inside a transaction with explicit ROLLBACK on suspicion.

BEGIN;

-- The AI generated:
-- UPDATE users SET active = false WHERE last_login < NOW() - INTERVAL '90 days';

-- Verify first:
SELECT id, email, last_login FROM users WHERE last_login < NOW() - INTERVAL '90 days';
-- Look at the count and a sample. Does it match what you expect?

-- Then run the UPDATE:
UPDATE users SET active = false WHERE last_login < NOW() - INTERVAL '90 days';
-- Check the affected row count matches your SELECT.

COMMIT;  -- or ROLLBACK if anything looks off

This is more work than just running the AI’s suggestion. It catches the bugs that matter.

Specific failure modes I’ve seen

A short list of real-world AI-SQL mistakes I’ve caught (or failed to catch):

The implicit JOIN explosion. AI generated a query joining three tables, missed an ON clause, produced a Cartesian product. On small data this looked like a slow query; on production it would have OOM’d the box.

The bool-NOT-bool trap. AI generated WHERE NOT user_active when the column was is_active. Postgres is permissive about this and inferred the wrong condition. The query returned the opposite of what it should have. Caught in EXPLAIN by noticing the row count was suspiciously high.

The timezone bug. AI generated a query using CURRENT_DATE for “today,” when our application stores timestamps in UTC and our users span timezones. The query returned wrong results for users in different time zones. Took two weeks to notice.

The window function misuse. AI generated ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at DESC) — fine for “latest per user” — but used it in a WHERE clause directly, which Postgres doesn’t allow. The AI then “fixed” it by wrapping in a subquery that scanned more rows than necessary.

The DELETE-too-broad. AI generated a DELETE that was syntactically correct but had a WHERE clause that matched 10x what was intended. Caught because I’d internalized the “convert to SELECT first” habit. Would have been a real incident otherwise.

The workflow that survives

The pattern that makes AI-SQL work safely:

  1. Show the AI your schema. Don’t make it guess.
  2. Generate the query. Read it. Make sure you understand what it claims to do.
  3. Run it as SELECT against a read-only context. Verify the row count and sample.
  4. Run EXPLAIN ANALYZE. Verify indexes, scan types, no surprises.
  5. For mutations, wrap in a transaction with explicit verification before COMMIT.
  6. For anything touching production, get a second pair of eyes.

Steps 3-6 are the discipline that AI doesn’t change. The AI accelerates step 2 (writing the query). Everything else stays.

If you’ve been skipping steps 3-6 because “the AI seems to get it right” — you’re collecting risk. The 95% of queries the AI gets right hide the 5% where it doesn’t, and the 5% are concentrated in the high-stakes mutations.

What this is not

This isn’t an argument against using AI for SQL. AI is genuinely useful for SQL. The argument is that “useful” and “trust the output” are different things. The verification work the discipline requires is real time. The accident prevention is also real.

For the work I do — analytics queries, schema migrations, occasional bulk updates — AI shaves real time off the writing phase and adds real time to the verification phase. Net is still positive, often substantially so. The point is to know which phase saved time and which phase you need to keep doing carefully.