PRODSoeverein Europees BaaS-platformOpen Dashboard →

Native AI · 8 min gelezen

Tutorial: bouw een NL2SQL-endpoint op Postgres

Affane Daylami · Fondateur · 28 augustus 2026

Terug naar blog

Deze tutorial laat zien hoe u een vraag in het Frans kunt ontvangen, deze kunt omzetten in een gevalideerde en begrensde SQL-query en vervolgens het resultaat kunt retourneren - zonder ooit een ongecontroleerde SQL uit te voeren. Bij elke stap wordt de feitelijk gegenereerde SQL weergegeven, niet alleen het eindresultaat.

Deze Engelse tekst is automatisch gegenereerd op basis van het Franse origineel en is nog niet beoordeeld.
Deze pagina is automatisch vertaald. De Engelse versie is gezaghebbend.

De NL2SQL-engine van Aurabase maakt deel uit van denative AI die is geïntegreerd in de backend: geen service van derden om in elkaar te zetten. Vereisten om deze handleiding te volgen: een bestaand Aurabase-project, een eenvoudig databaseschema voor het voorbeeld en een project-API-sleutel.

#
Doelstelling

Wat je gaat bouwen

Een eindpunt dat een vraag in natuurlijke taal ontvangt, deze omzet in een gevalideerde en begrensde SQL-query en vervolgens het resultaat retourneert. De engine voert gegenereerde SQL nooit uit zonder controle: elke query doorloopt syntactische validatie voordat deze de database bereikt.

Info

Deze tutorial maakt gebruik van de @aurabase/aurabase-js JavaScript SDK en de equivalente onbewerkte HTTP-aanroep, zodat je vanuit elke taal kunt meevolgen.

#
Onder de motorkap

Hoe de NL2SQL-engine werkt

De vraag gaat via een geconfigureerde LLM – OpenAI, Anthropic (Claude) of Gemini, de drie native providers – die een kandidaat-SQL genereert. Deze SQL wordt nooit uitgevoerd zoals hij is: hij passeert een validator die de syntaxisboom (sqlparser) ontleedt, alleen eenvoudige SELECT-query's toestaat en een begrensde LIMIT toevoegt als er een ontbreekt.

De validator wijst CTE/WITH, subquery's, UNIONS, vergrendelingsclausules (FOR UPDATE) en elke functie buiten een witte lijst expliciet af (count, sum, avg, min, max, lower, upper, coalesce, date_trunc, now). Joins met meerdere tabellen worden ondersteund.

Vraag → LLM (OpenAI/Claude/Gemini) → AST-validatie (sqlparser) → Bounded LIMIT → SELECT-uitvoering

Het opgevraagde diagram wordt nooit door uw verzoek geleverd: het wordt geïntrospecteerd vanuit de werkelijke basis van het project. Een veld schema, allowed_schema of schema_context dat in de hoofdtekst van het verzoek wordt verzonden, wordt expliciet geweigerd (400-fout) in plaats van stilzwijgend genegeerd. Alleen de server beslist wat er werkelijk bestaat.

#
Stap 1

Configureer het NL2SQL-eindpunt

Met de JavaScript SDK stelt de Aurabase-client aura.ai.nl2sql()bloot. De handtekening is nl2sql(question, options): het schema maakt er geen deel van uit, het wordt geïntrospecteerd aan de serverzijde.

app/api/ask/route.tstypescript
import { aura } from '@/lib/aurabase'

export async function POST(req: Request) {
  const { question } = await req.json()

  const { data, error } = await aura.ai.nl2sql(
    question,
    { limit: 50 }
  )

  if (error) return Response.json({ error }, { status: 400 })
  return Response.json(data)
}

In onbewerkte HTTP is het eindpunt POST /v1/ai/{project_id}/nl2sql, geverifieerd door de API-sleutel van het project.

terminalbash
curl -X POST https://<votre-gateway>/v1/ai/<project_id>/nl2sql \
  -H "apikey: <votre-cle-api>" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "Combien de commandes ont été passées ce mois-ci par des clients premium ?",
    "limit": 50
  }'
Velden geweigerd door de server

Stuur geen schema, noch allowed_schema, noch schema_context in de hoofdtekst van het verzoek: het opgevraagde schema wordt bepaald door de server, deze velden worden expliciet afgewezen (400) in plaats van stil overschreven.

#
Stap 2

Test met een echte vraag in het Frans

Vraag verzonden: “Hoeveel bestellingen zijn er deze maand door premiumklanten geplaatst?”. Hier is de vorm van de daadwerkelijk weergegeven SQL (tabelnamen en kolommen zijn afhankelijk van uw schema):

reactie (uittreksel)json
{
  "data": {
    "sql": "SELECT count(*) FROM orders WHERE customer_plan = 'premium' AND created_at >= date_trunc('month', now()) LIMIT 50",
    "explanation": "Compte les commandes de ce mois pour les clients premium.",
    "confidence": 0.85,
    "tables": ["orders"],
    "columns": ["customer_plan", "created_at"],
    "limit": 50,
    "limit_injected": false
  },
  "meta": null
}

limit_injected geeft aan of de LIMIT uit de sjabloon komt of door de server is toegevoegd. confidence is een heuristiek over de vorm van het antwoord (goed gevormd SQL-blok of niet) - geen maatstaf voor de semantische correctheid van de gegenereerde SQL. Een slecht geformuleerde vraag retourneert een expliciete fout in plaats van een gehallucineerde SQL: als de gegenereerde SQL bijvoorbeeld een tabel opvraagt ​​die niet in uw schema staat, worden in het bericht de feitelijk beschikbare tabellen genoemd.

#
Stap 3

Veilige productie

Drie controles vóór implementatie: is het rijplafond (LIMIT) aangepast aan uw volume, blijft de Postgres-rol die door de engine wordt gebruikt beperkt tot het projectschema en hebben de gevoelige tabellen een actief RLS-beleid - NL2SQL bevraagt dezelfde database als de rest van uw applicatie, deze heeft standaard geen uitgebreide toegangsrechten.

  • De standaard line cap is configureerbaar aan de serverzijde; een gevraagde waarde boven de serverlimiet wordt expliciet geweigerd in plaats van stilletjes verlaagd.
  • Toegang tot de systeemcatalogus (pg_catalog, information_schema) en niet-projectschema's wordt geblokkeerd door de validator, ongeacht uw RLS-beleid.
  • RLS blijft uw laatste verdedigingslinie bij gevoelige tabellen: de validator beperkt de vorm van de SQL, niet de zakelijke rechten op de gegevens.
#
Eerlijkheid

Huidige limieten waar u rekening mee moet houden

De engine is strikt leesbaar: alleen SELECT-verzoeken worden geaccepteerd. Elke poging totINSERT, UPDATE, DELETE, DROP, CREATE of ALTER gegenereerd door de sjabloon wordt vóór uitvoering afgewezen. Dit is geen promptconventie, het is een regel die wordt opgelegd op het niveau van de syntaxisboom.

Andere structurele limieten: geen subquery's, geen CTE/WITH, geen UNION en een gesloten witte lijst van tien SQL-functies. Een vraag die uiteraard om een ​​subquery vraagt ​​(“klanten die nog nooit hebben besteld”) moet opnieuw worden geformuleerd zodat deze in een eenvoudige SELECTpast, of moet anders worden afgehandeld aan de kant van de toepassing.

#
Ga verder

RAG en agenten

NL2SQL behandelt gestructureerde vragen over uw relationele data. Voor vragen over ongestructureerde inhoud (documenten, notities, tickets) vertrouwt de native RAG van Aurabase op pgvector en een HNSW-zoekopdracht. Beide mogelijkheden – en hoe u ze kunt combineren in een agent – ​​worden gedetailleerd beschreven op de Native AI op Postgres-pagina.

#
Veelgestelde vragen

Veelgestelde vragen

Werkt NL2SQL met een complex schema (meerdere joins)?+
Joins met meerdere tabellen worden ondersteund door de validator. Aan de andere kant worden subquery's en CTE/WITH expliciet afgewezen: een vraag die uiteraard om een ​​subquery vraagt, moet opnieuw worden geformuleerd om in een eenvoudige SELECT met joins te passen, of op een andere manier aan de applicatiekant worden afgehandeld.
Welke LLM-aanbieder kiezen voor NL2SQL?+
De drie native providers (OpenAI, Anthropic/Claude, Gemini) worden door de validator gelijk behandeld: geen enkele heeft een structureel voordeel bij de validatie van de gegenereerde SQL. De kosten en latentie zijn afhankelijk van het specifieke model dat voor uw project is geconfigureerd. Vergelijk ze op uw eigen volume in plaats van een algemene aanbeveling te volgen.

KLAAR VOOR IMPLEMENTATIE?

Uw backend in vijf minuten.

Geen creditcard vereist · 500 MB gratis · 50.000 MAU