Skip to content
guide

Text-to-SQL Explained: How Natural Language Becomes a Database Query

Text-to-SQL converts a question written in ordinary language into SQL. Some tools return a query to copy into an editor; others execute it and return a table or chart.

By the Datarelix Team · Published · Updated · Last verified

Text-to-SQL turns a question written in ordinary language into a SQL query by combining the question with the database schema: table and column names, types, relationships and any descriptions. The generated query is a proposal about what you meant, so how it was generated, whether it was validated before running and what came back with the result decide whether the answer can be trusted. This guide follows one reporting question from words to an executed query, then shows the workflow Datarelix uses.

How does a reporting question become a query?

A business user may need monthly sales without writing SQL. An analyst may want a first draft to inspect and refine. A text-to-SQL tool combines your question with information about the database, then generates SQL using its table and column names.

Consider this question against a retailer’s schema: “Show completed sales by month for April through June 2026, in EUR.” Here is a PostgreSQL query for it:

SELECT date_trunc('month', ordered_at) AS month,
       SUM(total_eur) AS completed_sales_eur
FROM orders
WHERE status = 'completed'
  AND ordered_at >= DATE '2026-04-01'
  AND ordered_at < DATE '2026-07-01'
GROUP BY 1
ORDER BY 1;

The table must actually contain these columns, and total_eur must match the agreed sales definition. The query groups matching orders by month; a month with no matching orders is absent unless the query explicitly fills the gap. It does not subtract refunds or convert currencies.

The same task is possible with handwritten SQL. Text-to-SQL vs manual SQL compares the work involved in producing, reviewing and reusing the answer.

What does the tool need to know?

Schema context supplies table names, columns, types and relationships. Business descriptions explain which table is current, what a status means and which amount is appropriate for reporting. Access permissions determine which data can be queried.

Missing detailWhy it changes the answerUseful clarification
Meaning of salesOrders, invoices and receipts are different measures“Use completed order value before refunds.”
Reporting period“Last quarter” and “last 90 days” differGive exact dates or name the calendar period.
Table choiceAn old table may resemble the current oneIdentify the approved reporting table.
Join relationshipOne order can have several payments or refundsDescribe the relationship and review its use.

Descriptions help, but do not guarantee a correct interpretation. See improving schema context.

Generation, execution and checking are separate capabilities

When comparing tools, establish whether they only generate SQL, execute it, show the executed statement, and retain results. Check their access controls and retry behavior separately. A product can provide several of these capabilities; an “AI SQL generator” label does not tell you which ones.

Database dialect matters too. PostgreSQL, MySQL, BigQuery and Snowflake use different date functions and identifier rules. Use a tool that supports the source you will connect, and test with a question you can independently check.

In Datarelix, credentials stay outside model context, while questions, schema descriptions and selected single-row result values can reach the model, and results are stored with the run. The security overview sets out what flows where.

How Datarelix processes the question

This is Datarelix’s workflow; other text-to-SQL products may divide the work differently.

1. Assemble schema context

Table and column names, types, declared relationships and reviewed descriptions help identify the relevant data. This schema context does not contain sample rows. A question can still contain information you type yourself, and selected values from a single-row answer may be used for a follow-up. Connection secrets remain outside model context.

2. Generate a structured request

The model proposes a plan containing the query and any analysis steps. At this stage, producing SQL does not run it. A structured request lets the service check its fields before passing an accepted query to execution.

3. Validate the proposed query

Datarelix parses the SQL and applies read-only validation before execution; the read-only AI analytics controls guide covers what that validation does and does not protect. A CTE is acceptable only when its contents also meet those restrictions; starting a statement with WITH does not make it a read. KQL and ES|QL use their own validators. Output limits constrain returned rows, not necessarily the volume a database scans. Database permissions remain part of the boundary.

4. Execute using the connection

The backend uses the connection credential to contact the source. Credentials are also needed for connection checks and schema discovery. They are not given to the model. The accepted query runs against the data visible to that database identity.

5. Handle errors and record the result

A failed query can be revised within retry limits. An error may enter model context to support that correction; each revised query must pass validation again. The successful run records the executed query, its sources, result and execution information. Review the query that actually ran, because it may differ from the first proposal.

6. Review the business interpretation

Successful execution establishes that the database accepted the statement. A business user still needs the right reporting definition, and an analyst still needs the right grain, join and time boundary. Follow-up questions can refine a report, but a familiar-looking chart does not replace those checks.

From a plain-English question to SQL: a worked example

The examples below use a retailer’s customers, orders and order_items tables.

Question: “Who were our top 10 customers by completed order value before refunds in Q2 2026?”

Assume unit_price is in EUR and each order item belongs to one order. On PostgreSQL:

SELECT
  c.customer_id,
  c.name,
  SUM(oi.quantity * oi.unit_price) AS revenue
FROM customers AS c
JOIN orders AS o ON o.customer_id = c.customer_id
JOIN order_items AS oi ON oi.order_id = o.order_id
WHERE o.status = 'completed'
  AND o.ordered_at >= DATE '2026-04-01'
  AND o.ordered_at < DATE '2026-07-01'
GROUP BY c.customer_id, c.name
ORDER BY revenue DESC
LIMIT 10;

The same question against BigQuery produces a structurally identical query with dialect differences:

SELECT
  c.customer_id,
  c.name,
  SUM(oi.quantity * oi.unit_price) AS revenue
FROM `demo_retail.customers` AS c
JOIN `demo_retail.orders` AS o ON o.customer_id = c.customer_id
JOIN `demo_retail.order_items` AS oi ON oi.order_id = o.order_id
WHERE o.status = 'completed'
  AND DATE(o.ordered_at) >= '2026-04-01'
  AND DATE(o.ordered_at) < '2026-07-01'
GROUP BY c.customer_id, c.name
ORDER BY revenue DESC
LIMIT 10;

BigQuery uses backticks for these dataset-qualified identifiers. In this example, ordered_at is a TIMESTAMP and DATE(ordered_at) uses UTC unless a time zone is supplied. The right filter also depends on the table’s partitioning. Dialect support should be checked against your actual column types and reporting time zone; a date conversion is not required for every BigQuery query. See the BigQuery guide for partition and cost considerations.

Try one question before expanding the scope

Use an authorised connection and ask a question whose answer is known. Confirm its dates, sources and definition with the verification guide. Start with a reporting table you understand; complex joins can wait until someone has checked their meaning.

The quickstart covers the connection and first question. Datarelix queries existing data; database writes, migrations and administration require other tools.