Best Model for SQL: Schema Grounding Beats Model Choice
Models

Best Model for SQL: Schema Grounding Beats Model Choice

A wrong query returns rows rather than an error, which is why SQL generation fails quietly. What to feed the model and how to verify before trusting.

Most generated code announces its own failure. A wrong query does not. It runs, it returns a table, the numbers look like numbers, and somebody puts them in a report. The absence of a loud failure mode is what makes SQL generation different from every other code generation task.

It also shifts where the effort goes. Model capability matters less here than in most domains, because the dominant failure is not reasoning — it is the model not knowing what is in your database.

Schema grounding is most of the job

A model with no schema will invent one. It will produce a query against a users table with an email column and a created_at timestamp, because that is what most databases look like, and it will be wrong about yours in ways that are tedious to find.

Giving it the schema is the single highest-return action available, and how you give it matters. Raw DDL for every table is wasteful and dilutes attention across hundreds of irrelevant columns. A curated description of the tables relevant to the question, with column types, foreign keys and a one-line note on what each table actually holds, works far better at a fraction of the tokens.

The notes are the part people skip and the part that helps most. A column named status with values nobody can guess, or an amount stored in minor units, or a soft-delete flag that every query must filter on — none of that is in the DDL, and all of it changes the answer. For large schemas, retrieve the relevant subset per question rather than sending everything. Retrieval versus long context covers making that selection.

Dialect drift

SQL is a family of related languages that share a name. Date arithmetic, string functions, upsert syntax, window function support, JSON access and pagination all differ between engines, and models default to a blend of whatever dominated their training data.

The failure is usually loud — a syntax error — which makes it the least dangerous problem on this list. But it is a constant tax on iteration, and it is removed entirely by naming the engine and version in the system prompt.

Do that once and you stop seeing it. It is a one-line fix that teams rediscover repeatedly because nobody wrote it down.

The join is where the silence lives

The genuinely dangerous errors are the ones that produce plausible output.

A join to a table with multiple matching rows silently multiplies the rows on the other side, and any aggregate downstream is inflated. Nothing errors. The total is simply too high, and if nobody knows the right answer in advance, it ships.

Inner joins where a left join was meant quietly drop records that have no match. Filters in the WHERE clause of a left join convert it back to an inner join, which is a mistake experienced engineers make too. And null handling in aggregates differs from what most people assume, so a count and a count of a column can disagree without either being wrong.

These are not model-quality problems in the usual sense. Every model in the current field makes them. The defence is verification, not capability.

Verify with plans and counts, not by reading

Reading a generated query and deciding it looks right is the weakest available check, because these errors look right by construction.

Three mechanical checks catch most of it. Run EXPLAIN and look at the estimated row counts — a join that the planner expects to multiply rows tells you immediately. Run the query with a row limit and eyeball the shape before running it for real. And where you can, compute the same figure two ways and compare.

For anything that will be reused, ask the model to produce the query and a short explanation of what each join is doing and why, then check the explanation rather than the SQL. Errors of reasoning are easier to spot in prose than in a join clause.

Safety rails matter more than capability

The blast radius of a generated query is a function of your permissions, not the model.

Run generation against a read-only role. Enforce a statement timeout so an accidental cross join cannot saturate the database. Cap returned rows. Use a replica rather than the primary. Log every generated query with the prompt that produced it, so a wrong number can be traced back.

Never interpolate a model's output into a larger statement, and never let generated SQL run unreviewed against production writes. Generating SQL safely covers the full set of controls, and the same reasoning applies to any tool a model can call. Agent sandboxing covers the general pattern.

Structured output beats free-form SQL for applications

If a model is generating SQL inside an application rather than for a human to read, consider not having it emit SQL at all.

Have it emit a constrained structure — which table, which filters, which aggregation, which grouping — validated against a schema, and build the SQL yourself from that structure. You lose expressiveness and you gain the guarantee that nothing unexpected reaches the database.

This is a strictly better position for any query surface exposed to users, and it makes the model choice easier, because emitting a small JSON object is something even cheap models do reliably. Choosing a model for structured output and JSON mode mechanics cover the constraint side.

Recommendation

For everyday query generation with a well-described schema in context, a cheap model is sufficient. DeepSeek V4 Flash handles standard filtering, joins and aggregation, and the money saved is better spent on schema documentation.

Step up to DeepSeek V4 Pro or GLM-5.2 for analytical work — window functions, recursive queries, multi-CTE reports — where the reasoning is genuinely harder and a wrong answer is more costly to detect.

For very large schemas where the model must first work out which tables are relevant, treat it as a retrieval problem rather than a model problem, and consider a long-context model only after the retrieval approach has been tried and found wanting.

The decision rule: spend on the schema description first, the safety rails second, and the model tier last. That ordering is the opposite of what most teams do and it produces better queries for less money.

Common questions

Why is generated SQL riskier than generated application code?

Because a wrong query returns rows rather than an error. A duplicated join inflates an aggregate silently, and if nobody knows the correct answer in advance the wrong number ships. Most other code announces its own failure.

How should I give a model my schema?

Not as raw DDL for every table. Send the relevant subset with column types, foreign keys and a one-line note per table on what it actually holds — including the things DDL cannot express, like soft-delete flags, enum meanings and units.

Do I need a strong model for SQL?

Usually not for everyday filtering, joins and aggregation — a cheap model with a well-described schema is enough. Step up for window functions, recursive queries and multi-CTE analytical work where the reasoning is genuinely harder.

Similar articles

A/B Testing Two Models Without Fooling Yourself
Models
Models·9 min read

A/B Testing Two Models Without Fooling Yourself

Comparing two models on live traffic sounds simple and usually is not. Sample sizes, paired designs, and the metrics that actually settle the question.

Read
The Artificial Analysis Index Explained: What It Does Measure
Models
Models·9 min read

The Artificial Analysis Index Explained: What It Does Measure

A single number that ranks every model is convenient and easy to misread. What the AA Intelligence Index aggregates, and where it stops being useful.

Read
Best Model for Agentic Workflows: Reliability Compounds
Models
Models·9 min read

Best Model for Agentic Workflows: Reliability Compounds

An agent that is 95 percent reliable per step fails most thirty-step tasks. Why compounding error, not peak capability, decides which model to run in a loop.

Read