Was Text zu SQL wissen muss
Text zu SQL heißt, dass ein Sprachmodell eine Frage in Alltagssprache in eine SQL-Abfrage übersetzt. Das Modell hat Ihre Datenbank nie gesehen, also kann es Tabellen, die Sie nicht beschreiben, nur raten.
Modul 4 lehrt SQL, und Modul 63 verlangt von einem Modell eine feste Form. Diese Lektion klärt, was das Modell über Ihre Tabellen erfahren muss.
Am Ende dieser Lektion
Notiz
Ich kann ein Datenbankschema so knapp beschreiben, dass ein Modell daraus SQL schreiben kann.
Schlüsselwörter
| Begriff | Was er bedeutet | Beispiel |
|---|---|---|
| Text zu SQL | ein Modell macht aus einer Frage eine Abfrage | |
| Schema | die Tabellen und Spalten einer Datenbank | |
| Fremdschlüssel | eine Spalte, die auf eine Zeile einer anderen Tabelle zeigt | ausleihen.buch_id |
| Join | Zeilen zweier Tabellen über eine Spalte verbinden | |
| Hinweis | eine Zeile, die sagt, was die Werte einer Spalte bedeuten |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Ein Modell braucht Tabellen, Spalten und Joins
Um eine Abfrage zu schreiben, braucht das Modell drei Dinge. Es braucht die Tabellennamen, die Spalten jeder Tabelle und die Art, wie die Tabellen verbunden sind.
Ohne die Joins rät es. Ein geratener Join wie ausleihen.id mit buecher.id läuft ohne Fehler und liefert die falschen Bücher.
Beispiel: das Schema der Bibliothek
| Tabelle | Spalten | Verbunden mit |
|---|---|---|
| buecher | id, titel, jahr | Nichts |
| mitglieder | id, name | Nichts |
| ausleihen | id, buch_id, mitglied_id, monat, zurueck | buch_id mit buecher.id, mitglied_id mit mitglieder.id |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Manche Spalten brauchen einen Hinweis
Der Name einer Spalte sagt nicht immer, was ihre Werte bedeuten. In der Bibliothek ist zurueck gleich 1, wenn ein Buch zurück ist, und 0, solange es draußen ist.
Ein Modell, das nur den Namen liest, prüft vielleicht zurueck = „nein“ oder zurueck IS NULL. Ein kurzer Hinweis pro unklarer Spalte verhindert diesen Fehlgriff.
Beispiel: Namen, die einen Hinweis brauchen
| Spalte | Geraten ohne Hinweis | Der Hinweis |
|---|---|---|
| ausleihen.zurueck | zurueck = „nein“ | 1 wenn zurück, 0 solange draußen |
| ausleihen.monat | Ein Datum wie 2026-03-01 | 1 bis 12, in diesem Jahr |
| buecher.jahr | Jahr des Kaufs | Jahr der Veröffentlichung |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Ein häufiger Fehler
Warnung
Viele denken, ein Modell kenne ihre Datenbank schon. Es hat sie nie gesehen. Schicken Sie Tabellen, Joins und Hinweise mit jeder Frage mit, denn jede Anfrage beginnt bei null.
Eine kurze Beschreibung schlägt den ganzen CREATE-Text
Sie könnten jede CREATE-TABLE-Anweisung einfügen. Eine kurze Zeile pro Tabelle, danach die Joins und die Hinweise, sagt dasselbe in einer Form, die ein Modell leicht liest.
Bei einer Datenbank mit vierzig Tabellen schicken Sie nur die Tabellen, die die Frage braucht. Weniger Wörter kosten weniger und lassen weniger Raum für Missverständnisse.
Die Modellhilfe schreiben, Teil 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const basis = process.env.AI_URL || \"http://ai:4000\";' '// Die Token einer Antwort oder null, wenn sie keine nennt.' 'function zaehlen(daten, name) {' ' return daten.usage && typeof daten.usage[name] === \"number\" ? daten.usage[name] : null;' '}' '// Eine Antwort kann die Abfrage in einen umzäunten Block setzen: Wir behalten das Innere.' 'function sqlVon(text) {' ' const teile = text.split(String.fromCharCode(96).repeat(3));' ' const innen = (teile.length > 2 ? teile[1] : text).trim();' ' return innen.toLowerCase().startsWith(\"sql\") ? innen.slice(3).trim() : innen;' '}' > model.js"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Die Modellhilfe schreiben, Teil 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function fragen(nachrichten, probe, max) {' ' try {' ' const res = await fetch(basis + \"/v1/chat/completions\", {' ' method: \"POST\",' ' headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' ' body: JSON.stringify({ model: \"lab\", messages: nachrichten, max_tokens: max || 100 }),' ' signal: AbortSignal.timeout(30000),' ' });' ' if (res.ok === false) throw new Error(\"Status \" + res.status);' ' const d = await res.json();' ' return { text: d.choices[0].message.content, eingabe: zaehlen(d, \"prompt_tokens\"), ausgabe: zaehlen(d, \"completion_tokens\"), aufgezeichnet: false };' ' } catch (fehler) {' ' console.log(\"Aufgezeichnete Probe: Kein Modell hat geantwortet (\" + fehler.message + \").\");' ' return { text: probe, eingabe: null, ausgabe: null, aufgezeichnet: true };' ' }' '}' 'module.exports = { fragen, sqlVon };' >> model.js"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Die kleine Bibliotheksdatenbank schreiben, Teil 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { DatabaseSync } = require(\"node:sqlite\");' '// Eine erfundene Bibliothek: sechs Bücher, vier Mitglieder, neun Ausleihen.' 'const BUECHER = [[1, \"Der Salzweg\", 2019], [2, \"Hafen aus Glas\", 2021], [3, \"Eine Karte aus Regen\", 2015],' ' [4, \"Leise Maschinen\", 2023], [5, \"Sieben Kessel\", 2018], [6, \"Nördlich vom Mittag\", 2022]];' 'const MITGLIEDER = [[1, \"Anke\"], [2, \"Bernd\"], [3, \"Carla\"], [4, \"Dirk\"]];' '// id, buch_id, mitglied_id, monat, zurueck (1 zurück, 0 noch draußen)' 'const AUSLEIHEN = [[1, 1, 1, 3, 1], [2, 2, 1, 3, 1], [3, 3, 2, 3, 0], [4, 1, 3, 3, 1], [5, 1, 1, 4, 0],' ' [6, 4, 2, 4, 0], [7, 2, 3, 4, 1], [8, 5, 2, 5, 0], [9, 2, 4, 5, 0]];' > bibliothek.js"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Die kleine Bibliotheksdatenbank schreiben, Teil 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function fuellen(db, tabelle, zeilen) {' ' const marken = zeilen[0].map(function () { return \"?\"; }).join(\", \");' ' const einfuegen = db.prepare(\"INSERT INTO \" + tabelle + \" VALUES (\" + marken + \")\");' ' zeilen.forEach(function (zeile) { einfuegen.run(...zeile); });' '}' 'function oeffnen(datei) {' ' const db = new DatabaseSync(datei || \":memory:\");' ' db.exec(\"CREATE TABLE buecher (id INTEGER PRIMARY KEY, titel TEXT, jahr INTEGER)\");' ' db.exec(\"CREATE TABLE mitglieder (id INTEGER PRIMARY KEY, name TEXT)\");' ' db.exec(\"CREATE TABLE ausleihen (id INTEGER PRIMARY KEY, buch_id INTEGER REFERENCES buecher(id), \"' ' + \"mitglied_id INTEGER REFERENCES mitglieder(id), monat INTEGER, zurueck INTEGER)\");' ' fuellen(db, \"buecher\", BUECHER);' ' fuellen(db, \"mitglieder\", MITGLIEDER);' ' fuellen(db, \"ausleihen\", AUSLEIHEN);' ' return db;' '}' 'module.exports = { oeffnen };' >> bibliothek.js"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Das Skript für die Schemabeschreibung schreiben, Teil 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { fragen, sqlVon } = require(\"./model\");' 'const { oeffnen } = require(\"./bibliothek\");' 'const db = oeffnen();' 'const tabellen = db.prepare(\"SELECT name, sql FROM sqlite_master WHERE type = ? ORDER BY name\").all(\"table\");' 'function kurz(t) {' ' const spalten = db.prepare(\"SELECT name, type FROM pragma_table_info(?)\").all(t.name)' ' .map(function (s) { return s.name + \" \" + s.type; });' ' return t.name + \"(\" + spalten.join(\", \") + \")\";' '}' 'const verknuepfungen = [];' 'tabellen.forEach(function (t) {' ' db.prepare(\"SELECT * FROM pragma_foreign_key_list(?)\").all(t.name).forEach(function (k) {' ' verknuepfungen.push(t.name + \".\" + k.from + \" -> \" + k.table + \".\" + k.to);' ' });' '});' > schema.js"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Das Skript für die Schemabeschreibung schreiben, Teil 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const hinweise = [\"ausleihen.zurueck ist 1, wenn das Buch zurück ist, 0, solange es draußen ist\",' ' \"ausleihen.monat ist 1 bis 12, in diesem Jahr\"];' 'const schema = tabellen.map(kurz).concat(verknuepfungen, hinweise).join(\"\n\");' 'const ganz = tabellen.map(function (t) { return t.sql; }).join(\"\n\");' 'console.log(schema);' 'console.log(\"ganzer CREATE-Text: \" + ganz.length + \" Zeichen, kurz mit Hinweisen: \" + schema.length);' >> schema.js"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Das Skript für die Schemabeschreibung schreiben, Teil 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' ' const frage = \"Wie viele Ausleihen gab es im Monat 3?\";' ' const system = \"Antworten Sie mit genau einer SQLite-SELECT-Abfrage und sonst nichts.\";' ' const probe = \"SELECT COUNT(*) FROM ausleihen WHERE monat = 3;\";' ' const antwort = await fragen([{ role: \"system\", content: system },' ' { role: \"user\", content: schema + \"\nFrage: \" + frage }], probe, 120);' ' console.log(\"Das Modell schrieb: \" + sqlVon(antwort.text));' ' console.log(\"noch nicht geprüft: Das tun die Lektionen 2 bis 5\");' '}' 'main();' >> schema.js"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Das Schema beschreiben und fragen
docker exec -w /home/node/project agent node --experimental-sqlite --no-warnings schema.jsHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Was der Run ausgibt
| Zeile | Was sie zeigt |
|---|---|
| buecher(id INTEGER, titel TEXT, jahr INTEGER) | Eine kurze Zeile pro Tabelle |
| ausleihen.buch_id -> buecher.id | Eine Zeile pro Join, aus den Fremdschlüsseln gelesen |
| ausleihen.zurueck ist 1, wenn das Buch zurück ist, 0, solange es draußen ist | Ein Hinweis, den Sie von Hand geschrieben haben |
| ganzer CREATE-Text: 298 Zeichen, kurz mit Hinweisen: 364 | Die Größe der beiden Formen |
| Das Modell schrieb: SELECT COUNT(*) FROM ausleihen WHERE monat = 3; | Die Abfrage, oder eine Aufgezeichnete Probe, wenn kein Modell antwortet |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.