Pain points · English

The generated query was never checked

A query written from a sentence is only as safe as the check against real tables, columns, and relationships. Zero rows can be a denial.

Published

The question is ordinary: how many open invoices are older than 30 days? A text-to-SQL chat answers 0, in a sentence that reads like a result. Collections almost posts that the queue is clear.

The SQL, when someone finally opens it, is one of three things. It filters on status = 'Open' and the column stores 'OPEN'. It joins invoice lines and counts lines, then the chat paraphrases the count as invoices, and a later filter happens to leave none. Or the role cannot read the table, the database returns an error, and the chat renders that as "no records found." Zero looks like good news. It was never a measurement.

A query written from a sentence is only safe if someone checked it against the real tables, columns, and relationships before anyone acted on it. An access denial that looks like an empty result is worse than a wrong number, because the reader treats silence as a true zero.

What "checked" has to include

Checking is not a vibe that the sentence looks right. It is four looks at the statement.

The tables. Are they the ones that hold this fact, or a staging copy, a view with a hidden filter, a table of the same name in another schema?

The columns and the values. Does status contain the word the model guessed, or a code? Is the date the invoice date, the due date, or the created date of the row?

The relationships. A join from invoices to customers on a column that happens to be named id in both tables will run and mean nothing. A join through invoice lines multiplies rows. A count of that join is not a count of invoices.

The empty set. Zero rows is a result, and it is also what you see when the predicate matches nothing, when you queried the wrong schema, and when the role was denied and the tool swallowed the error. Those are different facts. A tool that collapses them has hidden the one you needed.

None of this requires you to write the SQL yourself. It requires the SQL to be visible, and it requires a person who will look before the number is repeated in a channel where people act on it.

Why the usual tools make the check harder or skip it

A SQL client shows the statement because you wrote it. You can still join on the wrong key. The advantage is that the text is the thing on screen, and a permission error arrives as an error. The client is a poor guard against a tired person, and it is a good guard against a paraphrase. You see the statement you are about to run.

A BI chart hides the query behind a title. A filter set last quarter, or a measure that counts lines, can produce a confident zero. The check exists if the tool will show the SQL. Many readers never open that panel. A spreadsheet has no catalog at all. The number is a formula over whatever was pasted, and an empty paste looks like a real zero.

Single-database text-to-SQL is the tool this pain is aimed at. It is fluent, and it is willing to answer when the sentence and the catalog disagree. Some products show the SQL. Some show a grid. Some show a sentence and a number, and the statement is behind a disclosure, or gone. An error and an empty set can look similar once a layer has paraphrased both as "I didn't find any records." The reader is no longer looking at the database. They are looking at a summary of a query they did not see.

The failure is not that a model wrote SQL. People write bad SQL too. The failure is shipping the number without the statement, and teaching the reader that silence means zero.

A check you can do on the next answer

Read the SQL before you repeat the number. Not a sample of the time. The time you are about to send it to someone who will act. Look for the table names, the join keys, the filters, and the expression inside the count. If the question was "invoices" and the count is over invoice_line, you are not done.

Check the names against the catalog you trust, not against the model's explanation of the catalog. List the distinct values of status if the filter is a word the model guessed. A minute of select distinct is cheaper than a wrong all-clear.

Say the grain in the question so the model has less room. "Count invoices, not invoice lines. Open means status in ('OPEN', 'OVERDUE'). Older than 30 days means due_date, not created_at." You can still be wrong. You will be wrong in a way you can see.

Treat an empty result as a question, not as an answer. Run the count with the filter removed. If that is also empty, check that you are on the right database and that the role can read the table. A denial and a true zero need different responses. One is a permissions problem. The other is a business fact. If the chat will not tell you which one you got, go to the database's own message, or run the same statement with a role you know can read the table. Do not let a paraphrase settle it.

Save the statement next to the number you sent. When the figure is challenged on Thursday, you can show the text. A number with no statement cannot be defended or corrected. It can only be replaced with another number.

If you cannot see the statement, do not use the number. Confidence in the prose is not a substitute for the check.

Where DataTug fits

DataTug's AI chat plans the question, runs it, and shows the query and the rows, on the sources the project opens. That is the part you can check. The sources marked as working today are SQLite, PostgreSQL, MySQL, Oracle, SQL Server, BigQuery, inGitDB, and REST APIs. The same project opens in the web app and in the CLI and terminal UI, and an agent can reach it through the Claude Code skills plugin or the MCP server.

Showing the query and the rows is the help. It is not a guarantee that every generated statement was validated against the catalog before it ran. It is not a guarantee that an access denial is always labeled as a denial. The homepage shows you the query and the evidence. You still read them. If the grid is empty, you still ask whether you were denied.

Try that on the public demo before you trust the pattern with your own invoices. It opens without an account. Personal and public projects are free. When you connect your own source, keep the rule from the middle of this article: no statement, no number.

Pain pointsNext: The same metric, two definitions, two numbers