Schemas ändern sich. SQLite macht das mit – meistens.
Sobald eine Tabelle existiert, willst du sie früher oder später umbenennen, eine Spalte hinzufügen, eine Spalte entfernen oder die ganze Struktur umbauen. SQLite deckt die typischen Fälle direkt mit DROP TABLE und ALTER TABLE ab und bietet für alles andere einen dokumentierten Workaround.
Der Haken: ALTER TABLE ist in SQLite deutlich eingeschränkter als in Postgres oder MySQL. Zu wissen, was geht und was nicht – und welches Rebuild-Muster bei den Nicht-Geht-Fällen greift – macht hier den Großteil des Know-hows aus.
SQLite-Tabelle löschen mit DROP TABLE
DROP TABLE entfernt die Tabelle samt aller Zeilen, Indizes und der darauf definierten Trigger. Ein Undo gibt es nicht:
Damit ist die Tabelle weg. Eine Abfrage darauf würde jetzt den Fehler no such table: scratch werfen.
Wenn du dir nicht sicher bist, ob die Tabelle überhaupt existiert – typischer Fall in Setup-Skripten –, hängst du einfach IF EXISTS an. Dann passiert stillschweigend nichts, falls die Tabelle fehlt:
Ohne IF EXISTS würde der zweite DROP einen Fehler werfen. Mit der Klausel laufen beide sauber durch.
Fremdschlüssel können ein DROP blockieren
Wenn die Fremdschlüssel-Prüfung aktiv ist (PRAGMA foreign_keys = ON;) und eine andere Tabelle auf die zu löschende Tabelle verweist, schlägt das Löschen fehl:
sqlite> PRAGMA foreign_keys = ON;
sqlite> DROP TABLE users;
Runtime error: FOREIGN KEY constraint failed
Du hast mehrere Möglichkeiten: die referenzierende Tabelle zuerst löschen, die referenzierenden Zeilen entfernen oder den Foreign Key gleich beim Anlegen mit ON DELETE CASCADE definieren. SQLite wird die referentielle Integrität nicht stillschweigend aushebeln.
ALTER TABLE: Die vier möglichen Operationen
ALTER TABLE in SQLite unterstützt genau vier Operationen:
Jede dieser Anweisungen läuft als einzelnes Statement. Die ersten beiden sind praktisch kostenlos – sie passen lediglich das Schema an. Auch ADD COLUMN geht flott: SQLite schreibt die Tabelle nicht neu, sondern vermerkt nur die neue Spaltendefinition. DROP COLUMN ist hingegen aufwendiger – hier muss SQLite jede Zeile neu schreiben, um die Daten der Spalte tatsächlich zu entfernen.
SQLite ALTER TABLE ADD COLUMN mit Standardwert
Wenn du in SQLite eine Spalte zu einer bestehenden Tabelle hinzufügst, ist sie für alle vorhandenen Zeilen zunächst NULL – es sei denn, du legst einen Default-Wert fest:
Beide bestehenden Zeilen bekommen 'active' eingetragen. Der Default muss eine Konstante sein – SQLite akzeptiert weder CURRENT_TIMESTAMP noch irgendeinen anderen nicht-konstanten Ausdruck als Default bei ADD COLUMN. Der Grund: Es braucht einen Wert, der sich auf alle vorhandenen Zeilen anwenden lässt, ohne pro Zeile neu ausgewertet zu werden.
Wenn du NOT NULL ohne Default brauchst, musst du die Spalte zunächst als nullable hinzufügen, sie per UPDATE befüllen und anschließend die Tabelle neu aufbauen, um das Constraint zu setzen. Damit sind wir auch schon bei den Grenzen von ALTER TABLE.
Was ALTER TABLE in SQLite nicht kann
Dinge, die in Postgres oder MySQL funktionieren, in SQLite aber nicht:
- Den Datentyp einer Spalte ändern (
ALTER COLUMN ... TYPE ...). - Den Default einer Spalte direkt ändern.
NOT NULL,CHECK,UNIQUEoderPRIMARY KEYan einer bestehenden Spalte hinzufügen oder entfernen.- Einen Foreign Key auf eine bestehende Spalte legen.
- Spalten umsortieren.
Jeder dieser Versuche endet mit einem Syntaxfehler. Eine ALTER COLUMN-Klausel gibt es in SQLite schlicht nicht. Die offizielle Antwort ist in allen Fällen dieselbe: Tabelle neu aufbauen.
Das Rebuild-Pattern
Wenn ALTER TABLE nicht weiterhilft, legst du eine neue Tabelle mit dem gewünschten Schema an, kopierst die Daten rüber, löschst die alte und benennst die neue um. Pack das Ganze in eine Transaktion, damit es entweder komplett klappt oder gar nicht:
Jetzt ist users.age eine Ganzzahl mit Check-Constraint und email ist NOT NULL. Die Daten sind beim Umbau einfach mitgewandert.
Ein paar Dinge, die du in der Praxis beachten solltest:
- Foreign Keys vorher abschalten. Wenn andere Tabellen auf deine verweisen, setze
PRAGMA foreign_keys = OFF;vor der Transaktion undPRAGMA foreign_keys = ON;danach. Sonst scheitert dasDROP TABLE. Das Pragma lässt sich innerhalb einer Transaktion nicht ändern – also unbedingt außerhalb setzen. - Indizes und Trigger neu anlegen. Mit der alten Tabelle verschwinden auch deren Indizes und Trigger. Lege sie nach dem Umbenennen wieder auf der neuen Tabelle an.
- Views prüfen. Views, die auf die Tabelle verweisen, zeigen in ihrem gespeicherten SQL noch auf den alten Namen. Alles, was auf geänderte Spalten zugreift, musst du neu aufbauen.
Das Rebuild-Muster ist umständlich, aber zuverlässig. Genau so machen es Migrations-Tools wie Alembic oder Rails intern, wenn sie auf SQLite arbeiten.
Mehrere Tabellen löschen in SQLite
Es gibt kein einzelnes Statement, um mehrere Tabellen auf einmal zu löschen – du führst DROP TABLE einfach pro Tabelle aus. In einer Transaktion, wenn du sie als Einheit zusammenfassen möchtest:
Wenn man die drei Drops in eine Transaktion packt, gilt das Alles-oder-nichts-Prinzip – entweder funktionieren alle drei oder keiner. Praktisch ist das vor allem dann, wenn man zusammenhängende Tabellen abräumen will, die unterwegs an Foreign Keys scheitern könnten.
Was du mitnimmst
DROP TABLEentfernt eine Tabelle samt zugehöriger Indizes und Trigger. Für idempotente Skripte nimmst duDROP TABLE IF EXISTS.ALTER TABLEin SQLite kann genau vier Dinge: Tabelle umbenennen, Spalte umbenennen, Spalte hinzufügen, Spalte löschen.- Für alles andere – Typänderungen, neue Constraints, Foreign Keys auf bestehenden Spalten – baust du die Tabelle innerhalb einer Transaktion neu auf.
- Achte beim Neuaufbau auf Foreign Keys, Indizes, Trigger und Views. Die wandern nicht automatisch mit den Daten mit.
Als Nächstes: Daten einfügen
Ein ganzes Kapitel lang ging es um Tabellen und die Constraints, die ihnen Form geben. Jetzt wird es Zeit, sie auch zu befüllen – das nächste Kapitel startet mit INSERT, inklusive der Mehrzeilen-Variante, Default-Werten und der Frage, wie SQLite mit Inserts umgeht, die deine Constraints verletzen.
Häufig gestellte Fragen
Wie lösche ich eine Tabelle in SQLite?
Mit DROP TABLE table_name;. Setze IF EXISTS davor, damit das Statement still durchläuft, falls die Tabelle gar nicht existiert: DROP TABLE IF EXISTS users;. Beim Löschen verschwinden auch alle zugehörigen Indexe und Trigger. Sind Foreign Keys aktiv und andere Tabellen referenzieren noch, scheitert das DROP.
Was kann ALTER TABLE in SQLite eigentlich?
Genau vier Dinge: RENAME TO (Tabelle umbenennen), RENAME COLUMN ... TO ... (Spalte umbenennen), ADD COLUMN (neue Spalte anhängen) und DROP COLUMN (Spalte entfernen, ab SQLite 3.35). Mehr nicht – du kannst weder den Datentyp einer Spalte ändern noch deren Default nachträglich anpassen oder einer bestehenden Spalte ein Constraint verpassen.
Wie ändere ich Datentyp oder Constraints einer Spalte in SQLite?
Direkt geht das nicht – stattdessen nutzt man den klassischen Rebuild-Pattern: neue Tabelle mit dem gewünschten Schema anlegen, Daten per INSERT INTO new SELECT ... FROM old rüberschieben, dann DROP TABLE old und am Ende ALTER TABLE new RENAME TO old. Pack das Ganze in eine Transaktion, damit es atomar bleibt.