Schema vs data rows: does the AI see your data when it writes SQL?
When AI writes SQL, two different things can leave your machine: the schema and the rows. Why schema is enough, and why sending rows should be opt-in.
When an AI assistant writes SQL for you, something leaves your machine and travels to a language model. That much is unavoidable: the model cannot help with a database it knows nothing about. The question worth asking is not the vague “is this safe?” but the precise one: what exactly leaves, and is any of it my actual data?
There is a clean answer, and it rests on one distinction. Two very different things can travel to the model — the schema (the shape of your database) and the rows (the data inside it). They have completely different privacy profiles, and almost all the confusion about AI and data privacy comes from treating them as the same thing. One is a map. The other is the territory.
Disclosure: I work on SQL Sage, which I’ll use later as a concrete example. The distinction below holds regardless of which tool you use.
This article is only about egress — what information flows out. Whether the assistant can execute the SQL it writes is a separate axis, covered in why an AI SQL assistant should be read-only by default. Here the subject is narrower and, for most people, more worrying: when the AI writes a query, does it see the data?
Does the AI see my data?
Only if the tool sends it. And whether it does comes down to which of the two payloads it packages up. A well-designed assistant sends the schema and the text of your query — the facts it needs to write correct SQL — and stops there. A careless one, or a careless workflow, sends your rows too. Same model, same prompt box, radically different exposure. So “does the AI see my data?” is really “does this tool, in this flow, put my rows in the request?” To answer it you first have to know what a row is, and how it differs from a schema.
What is a schema, and what is a row?
The schema is metadata — the description of your database’s structure. Table names, column names, data types, primary and foreign keys, relationships, maybe a handful of constraints. Think of a customers table with columns id int, email varchar(255), created_at datetime, and a foreign key into orders. That sentence is schema. It describes the shape of the drawer without telling you what’s inside.
A row is what’s inside: (42, '[email protected]', '2026-03-01'). That is data — a real person’s email address, a real timestamp, a real identifier. A thousand such rows are your customer list. The schema says “there is a column called email holding text up to 255 characters.” The row says whose email it is.
This is the whole distinction. Schema describes; rows contain. And it is exactly the line between information the model needs and information it doesn’t.
Why is the schema enough to write correct SQL?
Because writing, explaining, and optimizing a query is a problem about structure, not contents. To produce SELECT email FROM customers WHERE created_at > '2026-01-01', the model has to know that the table is called customers, that the column is email and not e_mail, that created_at exists and is a datetime it can compare against. None of that requires knowing a single actual email address. The row values are irrelevant to building the query.
This is the same grounding that makes AI SQL correct in the first place: an assistant that reads your real schema instead of guessing it stops hallucinating table and column names. The important privacy consequence is that the thing which makes the AI accurate — schema introspection — is metadata, and metadata is categorically less sensitive than the rows it describes. You get correctness from the map. You do not need to hand over the territory to get it.
How does your data leak by accident, then?
Usually not through a tool’s schema introspection. It leaks through the human workflow around it. Three common vectors:
- Pasting a result set into a chat window. You run a query, get a grid of rows back, and paste it into an AI chat to ask “why do these numbers look off?” You have just sent production data — names, amounts, PII — to a third party, by hand.
- Error messages that carry values. A constraint violation or a conversion error often echoes the offending value:
duplicate key value '[email protected]'. Share that error with the model verbatim and the row data rides along inside it. - “Explain this output” flows. Attaching the actual output of a query so the model can interpret it means attaching the rows.
The lesson is that egress is a property of the whole workflow, not of one checkbox. A tool can be scrupulous about sending schema only, and you can still leak data the moment you paste a result grid into a browser tab.
What about sample values and distinct lists?
Here is the honest grey zone. Good grounding sometimes wants a little data-derived information — for instance, the distinct values of a low-cardinality status column, so the assistant writes WHERE status = 'shipped' instead of guessing a string that never appears. That is genuinely useful. It is also, strictly, information derived from your rows.
So draw the line on principle: anything that describes the structure is schema; anything read out of the contents of rows — a full result set, a sample row, or even the distinct values of a column — is data. The distinct-values case is a narrow, bounded, usually low-risk slice, nothing like shipping a table of customer PII. But it is not “schema,” and the clean way to handle it is to treat sending any row-derived information as a deliberate opt-in, not a silent default.
Why should sending rows be a conscious opt-in?
Because rows are where the sensitive material lives. Your customers’ emails, transaction amounts, health or financial records, anything regulated — all of it is in the rows, essentially never in the schema. (Table and column names can occasionally be sensitive, which is worth a glance, but it is a far smaller surface.) Sending a row to an external model is a data-processing event with real compliance weight in a regulated environment.
That is why the safe default is: rows never leave unless you say so. If you genuinely need the model to see sample rows — to reason about messy or malformed data — that should be an explicit, per-session, informed choice, made with full awareness that those specific rows are now going to an external model. It should never be the thing that happens quietly because you asked an innocent-looking question.
How do you check what a tool actually sends?
You can’t always see inside the tool, but you can ask the questions that matter:
- Does it state exactly what it sends? A tool that can’t tell you whether it sends schema only, or rows too, has already answered the question.
- Are rows a default or an opt-in? The right answer is opt-in, per session.
- Where does it send it? A tool that talks to your own AI account keeps the vendor out of the data path entirely; one that proxies through its own backend is one more party holding your schema.
- Does your own workflow smuggle rows in? Watch for pasted result sets and verbatim error text.
SQL Sage is built around that boundary: what leaves your machine is the schema and the SQL text — never your data rows, unless you opt in per session. It is keyless (it talks to your own Claude or ChatGPT account, so there is no vendor in the data path) and read-only by default. It works as an add-in for SQL Server Management Studio and as a plugin for DBeaver (the DBeaver plugin is Windows-only and covers PostgreSQL, MySQL/MariaDB, Oracle, SQL Server, and SQLite). You can see both on the products overview. SQL Sage is made by LumaSoft (LUMA sp. z o.o.) and is not affiliated with Microsoft, Anthropic, OpenAI, or DBeaver.
The takeaway
The entire privacy question about AI and SQL collapses into one distinction. The schema is the map — the names, types, and relationships that let the model write correct SQL, and metadata that is far less sensitive than it sounds. The rows are the territory — your actual data, which carries all the real risk and should move only when you deliberately decide it moves.
So “does the AI see my data?” has a precise answer, and it is in your hands: only if the rows are sent. Keep them home by default, send them only on purpose, and the model can be genuinely useful without ever meeting a single customer.