Menu

SQLite CREATE TABLE: Syntax, Constraints & Beispiele

Tabellen in SQLite anlegen: Spaltendefinitionen, Constraints, IF NOT EXISTS, temporäre Tabellen und CREATE TABLE AS SELECT – alles mit praktischen Beispielen.

Diese Seite enthält ausführbare Editoren — bearbeiten, ausführen und Ausgabe sofort sehen.

CREATE TABLE definiert ein Schema

Strukturierte Daten leben in SQLite immer in Tabellen – und jede Tabelle beginnt mit einem CREATE TABLE-Statement. Du vergibst einen Namen, listest die Spalten auf und kannst optional noch Constraints dranhängen. SQLite schreibt das Schema in die Datenbankdatei, und schon ist die Tabelle einsatzbereit.

Das kleinste sinnvolle Beispiel sieht so aus:

Drei Spalten, ein Primärschlüssel, eine NOT NULL-Regel. SQLite hat die id automatisch vergeben, weil es sich um einen Integer-Primärschlüssel handelt, und email durfte in der zweiten Zeile NULL sein, weil nichts anderes festgelegt war. Mehr ist es eigentlich nicht — Name, Spalten, Constraints — und alles Weitere auf dieser Seite ist nur eine Variation davon.

Die Syntax im Detail

Eine Spaltendefinition folgt dem Muster name TYP constraint constraint .... Der Typ ist im klassischen SQLite optional (dazu gleich mehr auf der Seite zur Type Affinity), aber es lohnt sich, ihn immer anzugeben — sowohl andere Entwickler als auch Tools verlassen sich darauf.

Ein paar Dinge, die hier wichtig sind:

  • Constraints werden einfach mit Leerzeichen aneinandergereiht: NOT NULL UNIQUE auf sku heißt, dass beide Regeln gelten.
  • DEFAULT 1 bei in_stock sorgt dafür, dass der INSERT diese Spalte weglassen darf.
  • SQLite verwendet INTEGER für boolesche Werte – einen echten BOOLEAN-Typ gibt es nicht. 0 steht für falsch, 1 für wahr.
  • Ein Komma nach der letzten Spalte ist ein Syntaxfehler. SQL ist hier strenger als JavaScript.

SQLite CREATE TABLE IF NOT EXISTS: kein Crash beim erneuten Ausführen

Führst du ein CREATE TABLE gegen eine Datenbank aus, in der die Tabelle schon existiert, wirft SQLite einen Fehler:

Fehler: Tabelle users existiert bereits

Beim ersten Mal ist das okay, beim hundertsten Mal nur noch nervig. Mit IF NOT EXISTS wird das Statement zu einer No-Op, sobald die Tabelle bereits existiert:

Das zweite CREATE TABLE macht schlicht gar nichts — kein Fehler, keine Schemaänderung. Genau diese Variante willst du in Startup-Code, Migrationsskripten und überall dort haben, wo dasselbe SQL mehrfach laufen kann.

Ein Wort der Warnung: IF NOT EXISTS prüft nur den Namen. Wenn bereits eine Tabelle mit diesem Namen existiert, aber andere Spalten hat, lässt SQLite sie unangetastet. Das Schema wird nicht "repariert" oder "aktualisiert" — dafür gibt es Migrationen.

Constraints: Regeln, die fest am Schema kleben

Mit Constraints verlagerst du Validierung direkt in die Datenbank. Diese vier wirst du ständig brauchen:

  • PRIMARY KEY — identifiziert eine Zeile eindeutig. Mehr dazu findest du im Doc zu Primary Keys.
  • NOT NULL — die Spalte muss einen Wert enthalten.
  • DEFAULT wert — wird verwendet, wenn ein INSERT die Spalte auslässt. Erlaubt sind sowohl Literale als auch Ausdrücke wie datetime('now').
  • CHECK (ausdruck) — muss für jede Zeile true ergeben.
  • UNIQUE (spalte, spalte) — Constraint auf Tabellenebene, der die Kombination eindeutig hält.

Constraints werden bei jedem INSERT und UPDATE geprüft. Verletzt eine Zeile eine Bedingung, wird sie abgewiesen und das Statement schlägt fehl. Fehlerhafte Daten direkt in der Datenbank abzufangen ist deutlich günstiger, als sie später aus der Applikation wieder herauszufischen.

Foreign Keys in SQLite

Ein Foreign Key sagt im Grunde: „Diese Spalte verweist auf eine Zeile in einer anderen Tabelle." Damit bleiben deine Daten konsistent — du kannst keinen Nutzer referenzieren, der gar nicht existiert, und mit den passenden Optionen kann das Löschen eines Nutzers automatisch dessen Bestellungen mitnehmen (Cascade).

Eine SQLite-Falle, die man sich gut einprägen sollte: Die Foreign-Key-Prüfung ist standardmäßig deaktiviert. Für jede Verbindung, die diese Constraints durchsetzen soll, muss PRAGMA foreign_keys = ON ausgeführt werden. Die meisten Treiber erledigen das automatisch oder bieten dafür eine Einstellung an – falls deiner das nicht tut, setz das Pragma direkt nach dem Verbindungsaufbau ab.

ON DELETE CASCADE bedeutet hier: Wird ein User gelöscht, verschwinden auch seine Posts mit. Daneben gibt es noch SET NULL, RESTRICT sowie das Default-Verhalten NO ACTION, das den Löschvorgang verweigert, sobald noch abhängige Datensätze existieren.

SQLite CREATE TABLE AS SELECT: Tabelle aus Abfrage erzeugen

Manchmal brauchst du einfach eine schnelle Kopie eines Abfrageergebnisses als neue Tabelle – als Snapshot, Backup oder Spieltabelle für eine Analyse. Genau dafür gibt es CREATE TABLE ... AS SELECT:

Die neue Tabelle übernimmt die Spaltennamen, die Typen (so gut es geht) und die Daten. Mindestens genauso wichtig ist aber, was eben nicht mitkommt: kein Primary Key, kein NOT NULL, keine Indizes, keine Foreign Keys. Du bekommst nur einen flachen Snapshot. Nutze das also als Ausgangspunkt für schnelle Auswertungen – und nicht, um ein echtes Schema zu klonen.

Wenn du nur die Struktur ohne die Daten willst, hängst du einfach WHERE 0 an:

Damit bekommst du eine leere Tabelle mit identischer Spaltenstruktur – praktisch für Archivtabellen, die du später befüllst.

Temporäre Tabellen in SQLite

Eine TEMP-Tabelle existiert nur, solange die aktuelle Datenbankverbindung offen ist. Sobald du die Verbindung schließt, ist sie weg – kein Aufräumen nötig, kein Schema-Müll, der zurückbleibt:

Sinnvolle Einsatzgebiete: Zeilen für eine mehrstufige Abfrage zwischenspeichern, Zwischenergebnisse parken, die für einen CTE zu unhandlich sind, oder verbindungsspezifische Daten in einer länger laufenden Session abschotten. CREATE TEMP TABLE und CREATE TEMPORARY TABLE bedeuten dasselbe.

Du kannst das auch mit AS SELECT kombinieren: CREATE TEMP TABLE snapshot AS SELECT ... ist ein typisches Muster, um ein Zwischenergebnis mitten in einer Analyse einzufrieren.

Namen in Anführungszeichen setzen

Spalten- und Tabellennamen sind in den meisten Fällen schlichte Bezeichner. Falls du aber ein reserviertes Wort oder einen Namen mit Leerzeichen brauchst, packst du ihn entweder in doppelte Anführungszeichen (so will es der SQL-Standard) oder in Backticks (eine MySQL-Eigenheit, die SQLite ebenfalls akzeptiert):

Es funktioniert, aber jedes Mal, wenn du die Tabelle ansprichst, hast du diese kleine Reibung. Bleib lieber bei schlichten Namen wie orders, selection oder user_id und spar dir die Anführungszeichen komplett.

Ein praxisnahes Beispiel

Jetzt setzen wir alles zusammen — ein kleines Schema für eine Tasks-App, mit IF NOT EXISTS, damit es bei jedem Start problemlos durchläuft:

Damit hast du ein Schema, das produktionsreif ist: idempotentes Anlegen, aktivierte Foreign Keys, ein CHECK, das done ehrlich hält, sinnvolle Defaults und Zeitstempel, die sich von selbst füllen.

Weiter geht's: Datentypen

Bei CREATE TABLE kannst du INTEGER, TEXT oder REAL schreiben – nur nimmt SQLite das mit den Typen bekanntermaßen nicht so genau. Auf der nächsten Seite schauen wir uns die fünf Storage Classes an, die SQLite tatsächlich intern verwendet – und warum der Typ, den du hingeschrieben hast, nicht immer der Typ ist, den du am Ende bekommst.

Häufig gestellte Fragen

Wie lege ich in SQLite eine Tabelle an?

Mit CREATE TABLE name (spalte1 TYP, spalte2 TYP, ...). Jede Spalte bekommt einen Namen und optional einen Datentyp; Constraints wie PRIMARY KEY, NOT NULL oder DEFAULT lassen sich direkt mit angeben. Das Statement wird sofort ausgeführt, und die Tabelle bleibt dauerhaft in der Datenbankdatei erhalten.

Was bewirkt IF NOT EXISTS bei CREATE TABLE?

CREATE TABLE IF NOT EXISTS name (...) legt die Tabelle nur an, wenn noch keine mit diesem Namen existiert. Ohne diesen Zusatz fliegt dir beim erneuten Ausführen gegen eine bestehende Datenbank ein table already exists-Fehler um die Ohren. In Migrations-Skripten und beim App-Start gehört das praktisch immer dazu.

Kann ich in SQLite eine Tabelle aus einem SELECT erzeugen?

Ja – CREATE TABLE new_name AS SELECT ... baut aus dem Ergebnis einer Abfrage eine neue Tabelle. Spaltennamen und Daten werden übernommen, Constraints, Primary Keys und Indizes der Quelltabelle dagegen nicht. Gut für Snapshots oder Zwischentabellen, aber kein Ersatz für ein sauber definiertes Schema.

Was ist der Unterschied zwischen einer temporären und einer normalen Tabelle?

CREATE TEMP TABLE (bzw. CREATE TEMPORARY TABLE) erzeugt eine Tabelle, die nur für die aktuelle Verbindung existiert und beim Schließen verschwindet. Normale Tabellen werden dauerhaft in der Datenbankdatei gespeichert. Temp-Tabellen eignen sich super, um Zwischenergebnisse zu parken, ohne das eigentliche Schema vollzumüllen.

Coddy programming languages illustration

Lerne mit Coddy zu programmieren

LOS GEHT'S