DEV Community

Vivek Kumar
Vivek Kumar

Posted on

Share the Schema, Not the Password: How Schema-Aware AI Stops Inventing Columns

You ask an AI assistant, "How many active subscriptions did we add last month?" It confidently returns a query:

SELECT COUNT(*)
FROM subscriptions
WHERE status = 'active'
  AND signup_date >= '2026-08-01';
Enter fullscreen mode Exit fullscreen mode

Clean, readable, and completely wrong for your database. Your table calls the column created_at, not signup_date. There is no status column — you track state in canceled_at IS NULL. The query either fails loudly with column "signup_date" does not exist, or worse, it runs against a lookalike column and hands you a confident, incorrect number that nobody catches until it's in a board deck.

This is a hallucinated column, and it happens for one simple reason: the model was guessing. It never saw your schema, so it invented plausible names based on the thousands of SaaS databases in its training data. The fix is not a cleverer prompt. It's giving the model the one thing it was missing — your actual schema — without handing over the keys to the whole database.

Why the model guesses in the first place

An LLM is a pattern machine. Ask it for SQL and give it nothing but the question, and it will produce SQL shaped like the most common answer to questions like yours. If most subscriptions tables in its training data have a status column, that's what you get — regardless of what your table actually looks like.

There are two obvious but bad ways to fix this. The first is to paste your schema into the chat by hand every time. That works for one query and falls apart by the third, and it goes stale the moment someone runs a migration. The second is to hand the AI a live database connection string so it can look things up itself. That "fixes" accuracy by creating a much bigger problem: now an AI tool holds credentials that can read every row of PII and write to production, and your chat log is one screenshot away from leaking them.

The better framing separates two things that usually travel together:

What the AI actually needs What it does NOT need
Table names, column names, and types Your database password
Primary and foreign keys Network access to the DB host
Constraints and relationships Write or DDL permissions
Enough structure to write correct SQL The ability to read raw rows unsupervised

To write correct SQL, the model needs your schema. It does not need your credentials. Once you see that split, the design almost writes itself: share the map, keep the keys.

Schema-awareness: grounding the model in reality

The term for feeding the model your real structure before it writes anything is schema grounding (or schema-aware reasoning). Instead of asking "what would a subscriptions query usually look like," the model first reads the actual definition:

-- What the model reads before writing a single line of SQL
CREATE TABLE subscriptions (
  id           BIGINT PRIMARY KEY,
  account_id   BIGINT REFERENCES accounts(id),
  plan         TEXT NOT NULL,
  created_at   TIMESTAMPTZ NOT NULL,
  canceled_at  TIMESTAMPTZ            -- NULL means still active
);
Enter fullscreen mode Exit fullscreen mode

Now the same question produces SQL grounded in what exists:

SELECT COUNT(*)
FROM subscriptions
WHERE canceled_at IS NULL
  AND created_at >= '2026-08-01'
  AND created_at <  '2026-09-01';
Enter fullscreen mode Exit fullscreen mode

No status. No signup_date. The model can't invent region or revenue out of thin air, because the boundaries of what it's allowed to reference are set by the schema in front of it. Grounding doesn't make the model smarter — it makes the space of possible answers smaller and truer.

Where the connection layer comes in

Manually pasting that CREATE TABLE block works for a demo. In real life you want the schema delivered automatically, kept current, and delivered without also delivering the credentials. That's exactly the job of a database connector layer — and it's the core idea behind the Model Context Protocol (MCP), the open standard for connecting AI clients to tools and data sources.

The pattern looks like this: a small server sits between the AI client and your database. It holds the connection details. It exposes a couple of capabilities to the AI — typically a way to read the schema and a way to run a read-only query — and nothing else. When the AI needs to write SQL, it asks the server for the schema, gets back real table and column definitions as structured data, and generates its query against that. When it runs the query, the server executes it on a read-only connection and returns rows.

// A generic, vendor-neutral connector config — note there is no
// password anywhere near the AI client
{
  "mcpServers": {
    "analytics-db": {
      "url": "https://your-broker.example.com/mcp",
      "auth": "oauth"          // token brokered here, never pasted into a prompt
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

A typical exchange, in plain terms:

Step Who does it What crosses the wire
1. "List the tables" AI → broker Table names only
2. "Describe subscriptions" AI → broker Columns, types, keys
3. Generate SQL AI (locally) Nothing — it's grounded now
4. Run the SELECT broker → DB Rows back, read-only

The AI got everything it needed to be accurate and nothing it could use to be dangerous. Managed brokers like Draxlr's MCP server implement exactly this shape — OAuth-based, read-only (SELECT only), able to hand the model your schema and run queries without the assistant ever seeing a credential — but the pattern is the point, and you can build a minimal version of it yourself in an afternoon.

The security dividend

Schema-sharing started as an accuracy fix, but it quietly solves a security problem too. Because the AI never receives credentials:

  • There are no long-lived secrets sitting in prompts, chat history, or config files that get committed to a repo by accident.
  • Access is centrally revocable — kill the token at the broker and every connected client loses access at once, no credential rotation across a dozen laptops.
  • The database is not network-exposed to every machine running an AI client; only the broker talks to it.
  • A read-only, SELECT-only connection means even a perfectly-worded "delete all canceled accounts" request has nowhere to land.

You get more accurate SQL and a smaller attack surface from the same architectural decision. That's rare.

Common mistakes and gotchas

Dumping a 400-table schema into context. Schema grounding consumes tokens, and a giant schema can blow past the context window or bury the relevant tables in noise. Expose a focused subset, or let the model list tables first and pull only the definitions it needs.

Sharing schema but skipping read-only enforcement. Grounding fixes accuracy, not authorization. If the underlying connection can write, a cleverly phrased request (or a prompt-injection in your data) can still do damage. Enforce SELECT-only at the database role, not just by asking nicely in a system prompt.

Assuming grounded means correct. A model that can see your schema will stop inventing columns, but it can still get joins or business logic wrong — using created_at when you meant activated_at. Always eyeball the generated SQL before it hits production, especially for anything aggregated.

Letting the schema go stale. If your connector caches the schema, a migration can put you right back to hallucinated columns. Make sure schema reads reflect the live structure, or refresh the cache on deploy.

Leaking data through the schema itself. Column names like patient_ssn or comments in your DDL can be sensitive. Share the structure you want the AI to see, not necessarily every internal table.

Key takeaways

AI invents columns because it's guessing without your schema. The fix is to ground it in your real structure — but you can do that without ever handing over your credentials. Split the two: the model needs the map (tables, columns, types, keys) to write correct SQL; it does not need the keys (passwords, write access, raw network reach) to do its job. A connector or MCP-style broker delivers the schema automatically, keeps it current, runs queries read-only, and holds the credentials so the AI never sees them. You end up with SQL that actually runs and a database that's harder to hurt.

Have you connected an AI assistant to your database yet? What broke first — the hallucinated columns, or the security review? Drop your setup (and your favorite "there is no such column" story) in the comments.


Sources and further reading: Introducing the Model Context Protocol (Anthropic), MCP Specification, Reducing Hallucinations in Text-to-SQL (Wren AI), Improving Text-to-SQL Accuracy with Schema-Aware Reasoning, Building MCP servers for your database (Microsoft). If you want a managed, read-only MCP server that implements this pattern, see the Draxlr MCP docs.

Top comments (0)