Skip to content
AI Dev Toolkit.
Esc
  • AI Token CounterCount tokens for GPT, Claude, Gemini, DeepSeek, Qwen and more.Tool
  • LLM API Cost CalculatorEstimate per-request, daily and monthly API costs.Tool
  • AI Model ComparisonCompare prices, context windows and features across models.Tool
  • AI Model Pricing PagesSpecs, real costs and cheaper alternatives for popular models.Tool
  • Context Window CheckerSee whether your text fits each model’s context window.Tool
  • Subscription vs API CalculatorFind out whether a chat plan or the API is cheaper for you.Tool
  • GPU / VRAM CalculatorCheck how much VRAM a local model needs and which GPUs fit.Tool
  • Prompt Caching CalculatorEstimate savings from prompt caching.Tool

Prompt template · Data

Text to SQL prompt from a database schema

Turn a question in plain English into one query for your schema and SQL dialect, with assumptions stated. Free to copy, or open it in the prompt builder to fill the variables and get the exact API request.

218 tokens unfilled · 319 with the example below · o200k_base (GPT-4o and later)

Template

The prompt

Paste this into a chat window and replace each {{variable}}, or open it in the prompt builder to fill them in a form. Sections are marked with XML tags, which every major model reads well.

Prompt (one message, plain text)
You are a database engineer who writes correct, readable {{dialect}} queries.

<context>
The schema:
<schema>
{{schema}}
</schema>

Notes on the data (meaning of columns, known quirks):
<data_notes>
{{data_notes}}
</data_notes>
</context>

<constraints>
- Use only tables and columns that exist in the schema. If the question can’t be answered from it, say which data is missing instead of writing a query.
- The query must be read-only (SELECT, or WITH … SELECT).
- Be explicit about how you handle NULLs, duplicates from joins, and time zones for date filters.
- Prefer clear CTEs over deeply nested subqueries.
- If the question is ambiguous (for example, “active customers”), pick the most reasonable reading and state it.
</constraints>

<output_format>
The query in one SQL code block, then a short list headed “Assumptions”. No other text.
</output_format>

<task>
Write one {{dialect}} query that answers this question: {{question}}
</task>
For an API call: system prompt and user message

With a system prompt, the role, constraints and output format stay fixed across calls (and can be cached), while the context and task go in the user message.

System prompt
You are a database engineer who writes correct, readable {{dialect}} queries.

<constraints>
- Use only tables and columns that exist in the schema. If the question can’t be answered from it, say which data is missing instead of writing a query.
- The query must be read-only (SELECT, or WITH … SELECT).
- Be explicit about how you handle NULLs, duplicates from joins, and time zones for date filters.
- Prefer clear CTEs over deeply nested subqueries.
- If the question is ambiguous (for example, “active customers”), pick the most reasonable reading and state it.
</constraints>

<output_format>
The query in one SQL code block, then a short list headed “Assumptions”. No other text.
</output_format>
User message
<context>
The schema:
<schema>
{{schema}}
</schema>

Notes on the data (meaning of columns, known quirks):
<data_notes>
{{data_notes}}
</data_notes>
</context>

<task>
Write one {{dialect}} query that answers this question: {{question}}
</task>

Variables

What to put in each variable

{{dialect}}
The database and version, such as PostgreSQL 17, MySQL 8.4, SQLite or BigQuery. Date functions and quoting differ between them.
{{schema}}
The CREATE TABLE statements for the relevant tables, with keys and indexes. DDL is more precise than a description.
{{data_notes}}
What the schema doesn’t say: that status is one of 'trial', 'paid', 'cancelled'; that timestamps are UTC; that deleted rows have deleted_at set. Write “none” if there are none.
{{question}}
The question in plain English, such as “monthly revenue from paid customers in 2026, by country”.

Use

When to use it

Use it for ad hoc analysis, for drafting a report query, or inside an internal tool that answers questions about your data. It works best with a small, relevant part of the schema rather than every table in the database.

Run generated queries against a read replica or with a read-only role, and check the results against a number you already know. A query can be valid SQL and still answer a slightly different question than the one you asked.

Structure

Why it’s structured this way

The schema goes in as DDL because column types, keys and constraints change what a correct query looks like. The data notes section carries the knowledge that lives in people’s heads, such as soft deletes and status values, which is the most common reason a syntactically correct query returns the wrong number.

The read-only rule is a safety constraint, not a style choice. It doesn’t replace database permissions, but it stops the model from helpfully suggesting an UPDATE. The refusal path (say what data is missing) prevents the model inventing a column that sounds right.

NULLs, join duplicates and time zones are named because they are where answers silently go wrong. The Assumptions list makes the model’s reading of an ambiguous question visible, so you can correct it before trusting the result.

Example

A filled-in example

{{dialect}}
PostgreSQL 17
{{schema}}
CREATE TABLE customers (id bigint PRIMARY KEY, country text NOT NULL, status text NOT NULL, deleted_at timestamptz);
CREATE TABLE payments (id bigint PRIMARY KEY, customer_id bigint REFERENCES customers(id), amount_cents integer NOT NULL, paid_at timestamptz NOT NULL, refunded boolean NOT NULL DEFAULT false);
{{data_notes}}
status is 'trial', 'paid' or 'cancelled'. Soft-deleted customers have deleted_at set. Amounts are in cents. All timestamps are UTC.
{{question}}
monthly revenue from paid customers in 2026, by country

What to look for. A good query filters status = 'paid' and deleted_at IS NULL, excludes refunded payments, groups by date_trunc('month', paid_at) and country, and converts cents to currency units. The Assumptions should say whether “paid customers” means current status or status at the time of payment, because the schema can’t tell.

The complete filled-in prompt (319 tokens)
Filled-in prompt
You are a database engineer who writes correct, readable PostgreSQL 17 queries.

<context>
The schema:
<schema>
CREATE TABLE customers (id bigint PRIMARY KEY, country text NOT NULL, status text NOT NULL, deleted_at timestamptz);
CREATE TABLE payments (id bigint PRIMARY KEY, customer_id bigint REFERENCES customers(id), amount_cents integer NOT NULL, paid_at timestamptz NOT NULL, refunded boolean NOT NULL DEFAULT false);
</schema>

Notes on the data (meaning of columns, known quirks):
<data_notes>
status is 'trial', 'paid' or 'cancelled'. Soft-deleted customers have deleted_at set. Amounts are in cents. All timestamps are UTC.
</data_notes>
</context>

<constraints>
- Use only tables and columns that exist in the schema. If the question can’t be answered from it, say which data is missing instead of writing a query.
- The query must be read-only (SELECT, or WITH … SELECT).
- Be explicit about how you handle NULLs, duplicates from joins, and time zones for date filters.
- Prefer clear CTEs over deeply nested subqueries.
- If the question is ambiguous (for example, “active customers”), pick the most reasonable reading and state it.
</constraints>

<output_format>
The query in one SQL code block, then a short list headed “Assumptions”. No other text.
</output_format>

<task>
Write one PostgreSQL 17 query that answers this question: monthly revenue from paid customers in 2026, by country
</task>

Models

Tips by model family

  • OpenAI GPT

    If your tool runs the query automatically, use Structured Outputs with fields for the SQL and the assumptions. OpenAI documents that this guarantees the schema, so you never have to parse SQL out of prose.

  • Gemini

    Google recommends always including few-shot examples. Two or three question-and-query pairs for your own schema teach naming and join patterns faster than more rules.

  • All models

    Put the schema in a fixed system prompt and only the question in the user turn. A long, unchanging prefix is what prompt caching discounts, and OpenAI’s guide recommends putting reusable content first.

Related

Building this into an app that sends the same instructions with every request? Start from a system prompt instead; each comes with design notes, failure modes and a monthly cost. In the system prompt library: SQL analyst with read-only safety.

Edited the template? Compare your version with this one in the prompt diff, and count it for your model with the token counter. In the glossary: prompt caching. Browse all 29 prompt templates.