AI can generate useful SQL from a database schema, but accurate results depend on the context and constraints you provide. This guide gives you a repeatable prompt engineering workflow for supplying schema details, selecting the correct SQL dialect, defining business rules, and validating generated queries before they reach a database.
Overview
Generating SQL with AI is best treated as a translation and review task, not as an instruction to “write a query” with no additional context. A model may produce syntactically valid SQL that uses the wrong table, assumes an incorrect relationship, applies an unsuitable date rule, or changes data when you intended to read it.
A reliable text-to-SQL workflow has five parts:
- Provide the relevant schema: Include table names, columns, data types, keys, relationships, and useful constraints.
- Name the SQL dialect: PostgreSQL, MySQL, SQL Server, and SQLite differ in functions, date handling, identifiers, and pagination syntax.
- Define the business meaning: Explain terms such as “active customer,” “monthly revenue,” or “latest order.”
- Constrain the operation: State whether the query must be read-only and whether mutations are prohibited.
- Validate the result: Review the query, run it against a safe environment, inspect the execution plan where appropriate, and compare results with known examples.
This approach reflects core prompt engineering best practices: give the model the information it needs, define the output clearly, and create a review step for consequential work.
Checklist by scenario
1. Prepare the schema context
Do not send an entire production database export by default. Start with the tables and columns needed for the request, and remove secrets, personal data, credentials, and irrelevant records. A schema-context worksheet can use this format:
Database purpose: [short description]
SQL dialect and version: [PostgreSQL/MySQL/SQL Server/SQLite + version if relevant]
Table: customers
Purpose: One row per customer
Columns:
- customer_id: integer, primary key
- email: text, unique
- created_at: timestamp
- status: text; allowed values include active, paused, closed
Table: orders
Purpose: One row per order
Columns:
- order_id: integer, primary key
- customer_id: integer, foreign key to customers.customer_id
- order_date: date
- total_amount: decimal
- status: text; paid, pending, cancelled
Known rules:
- Cancelled orders are excluded from revenue.
- A customer is active when customers.status = 'active'.
Explicitly identify relationships instead of expecting the model to infer them from similar column names. If a relationship is not enforced by a database constraint, describe it in plain language and mark it as an assumption.
2. Use a system prompt for stable guardrails
A system prompt can establish consistent behavior across many SQL requests. Adapt the wording to your environment:
You generate SQL for the stated database dialect using only the supplied schema.
Rules:
1. Do not invent tables, columns, joins, functions, or values.
2. Ask a clarifying question when the schema or business definition is insufficient.
3. Default to a read-only SELECT query unless the user explicitly requests another operation.
4. Never generate INSERT, UPDATE, DELETE, DROP, ALTER, TRUNCATE, or GRANT statements in this workflow.
5. Qualify ambiguous column names and explain every join.
6. State assumptions before presenting the query.
7. Return the SQL in one code block, followed by a short explanation and validation notes.
8. Use the specified SQL dialect rather than generic SQL when syntax differs.
If your application supports structured responses, request separate fields for assumptions, SQL, parameters, and validation steps. See the guide to structured output prompting for a related approach.
3. Use a focused user prompt
Pair the schema with a precise request. This copy-ready template is suitable for reporting queries:
Using the supplied schema, write a read-only [dialect] query that answers:
[plain-language question]
Requirements:
- Include only [requested fields].
- Define [business term] as [exact rule].
- Exclude [statuses, dates, or records to exclude].
- Group by [dimensions] and sort by [ordering].
- Use parameters for [user-supplied values].
- Do not invent schema elements.
Return:
1. Assumptions or ambiguities
2. SQL query
3. Explanation of each join and filter
4. Suggested validation checks
5. Potential performance concerns
For example, replace “monthly revenue” with a precise definition such as “the sum of total_amount for paid, non-cancelled orders, grouped by calendar month using order_date.” Business definitions are often more important than additional prose in the prompt.
4. Match the database dialect
| Dialect | Prompt guidance | Items to verify |
|---|---|---|
| PostgreSQL | Name PostgreSQL explicitly and state whether schema-qualified names are required. | Date and timestamp expressions, identifier quoting, casts, and pagination. |
| MySQL | Specify the MySQL version when function or syntax compatibility matters. | Date functions, identifier quoting, grouping behavior, and limit syntax. |
| SQL Server | State whether the query targets a particular database compatibility level. | Pagination, date functions, bracketed identifiers, and schema names. |
| SQLite | Tell the model that the database uses SQLite-specific type and date behavior. | Date storage conventions, supported functions, type affinity, and joins. |
This table is a prompt-planning aid, not a substitute for checking the documentation and behavior of the target database. If a query will move between systems, ask the model to identify portability risks rather than silently rewrite dialect-specific syntax.
5. Add examples when the rule is difficult
Few-shot prompting can clarify reporting conventions. Provide two or three small, non-sensitive examples showing the requested output and the correct interpretation. For instance, show how a cancelled order is excluded, how a customer with no orders should appear in a left join, or how a time zone boundary is handled. Examples should demonstrate the rule; they should not replace the schema or business definition.
What to double-check
- Columns and tables: Compare every identifier in the generated SQL with the supplied schema. A plausible name is not evidence that the column exists.
- Join logic: Confirm the join keys, direction, and expected row count. A one-to-many join can multiply amounts when aggregation occurs at the wrong level.
- Filters: Check status values, null handling, date boundaries, time zones, and whether conditions belong in
WHEREorHAVING. - Aggregation: Verify that selected non-aggregate columns are grouped correctly and that totals are not duplicated by joins.
- Parameters: Use bound parameters in application code instead of concatenating user input into SQL. Ask the model to mark parameters clearly.
- Safety: Review the statement type before execution. For unfamiliar or destructive operations, require human approval and test in a disposable or staging environment.
- Performance: Inspect filters, joins, sorting, and limits. Use an execution plan in a safe environment when a query handles a large or frequently accessed dataset.
- Meaning: Compare a small result sample with manually verified cases. A query can be valid SQL and still answer the wrong business question.
For repeated workflows, create a test set containing representative questions, expected tables, key filters, and known result characteristics. The LLM evaluation guide provides a broader framework for regression testing generated outputs.
Common mistakes
Using a vague request
“Show our best customers” leaves ranking criteria, time range, revenue definition, and ties unresolved. Replace it with a measurable request: specify the metric, period, exclusions, sort order, and result limit.
Providing only table names
Table names rarely reveal nullability, relationships, status semantics, or timestamp conventions. Supply columns and constraints for every table involved.
Letting the model infer joins
Similarly named fields may not represent the same entity. State the join path and ask for an explanation. If the relationship is uncertain, require a clarifying question instead of a guessed query.
Mixing dialects
Generated SQL may combine syntax from different database systems when the prompt says only “write SQL.” Name the dialect at the beginning and request a portability review when needed.
Executing without a review boundary
An AI database query generator should not be connected to unrestricted production execution by default. Separate generation from execution, enforce read-only permissions where possible, log the generated statement, and require approval for mutations or sensitive data access.
Overloading the prompt with irrelevant schema
More context is not always better. A large, unfiltered schema can make the relevant relationships harder to identify and may expose information that the model does not need. Retrieve only relevant schema context, much like the focused retrieval patterns described in this RAG tutorial.
When to revisit
Keep this SQL prompting workflow as a living checklist. Revisit it whenever the database schema changes, a report gains a new business rule, a query moves to another SQL dialect, or an application changes how generated SQL is reviewed or executed.
It is also worth reviewing before seasonal planning cycles and recurring reporting periods. Confirm that date ranges, fiscal calendars, status values, and definitions such as “active,” “customer,” or “revenue” still match the organization’s current usage. If a model, prompt framework, database version, or query tool changes, rerun a small evaluation set rather than assuming previous outputs will behave identically.
Before using a generated query, work through this final sequence:
- Paste the current, minimal schema context into the approved prompt.
- Name the exact SQL dialect and relevant version or compatibility requirements.
- Define the business terms, date rules, exclusions, and desired output.
- Request assumptions, SQL, join explanations, parameters, and validation checks.
- Compare identifiers against the schema and inspect the statement type.
- Test with known cases in a safe environment, then review performance and access controls.
- Record corrections as examples or prompt rules for the next iteration.
When an output remains inconsistent, use a structured debugging process rather than repeatedly adding vague instructions. The AI prompt debugging workflow can help isolate whether the problem is missing context, an ambiguous requirement, an unsuitable example, or an insufficient validation step.