CREATE TABLE fügt einer Datenbank eine neue Tabelle hinzu. Du gibst der Tabelle einen Namen und listest ihre Spalten auf, jeweils mit einem Datentyp und den Regeln (Constraints), denen ihre Werte folgen müssen. Die Beispiele funktionieren in PostgreSQL, MySQL, SQLite und SQL Server.
So verwendest du CREATE TABLE
Gib der Tabelle einen Namen und liste dann ihre Spalten in Klammern auf, durch Kommas getrennt. Jede Spalte bekommt einen Namen, einen Datentyp und optional Constraints wie PRIMARY KEY, NOT NULL, UNIQUE, DEFAULT oder CHECK:
CREATE TABLE table_name (
column_name data_type constraints,
another_column data_type constraints
);
CREATE TABLE customers (
id INTEGER PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE,
country CHAR(2) DEFAULT 'US',
signed_up DATE
);
INSERT INTO customers (id, name, email, signed_up)
VALUES (1, 'Ana Lima', 'ana@example.com', '2026-03-02');
SELECT * FROM customers;
-- Output:
-- id | name | email | country | signed_up
-- ---+----------+-----------------+---------+-----------
-- 1 | Ana Lima | ana@example.com | US | 2026-03-02
Die neue Tabelle bleibt leer, bis du Zeilen einfügst. Dieses Insert hat country weggelassen, daher hat die Zeile den Standardwert US bekommen.
Wichtige Regeln
-
SQLite erzwingt weder Typen noch Längen. Wo andere Datenbanken einen Wert ablehnen, der nicht zur Spalte passt, speichert SQLite ihn trotzdem. Füge
STRICTnach der schließenden Klammer hinzu, damit geprüft wird (eine strikte Tabelle akzeptiert nur die TypenINT,INTEGER,REAL,TEXT,BLOBundANY).
CREATE TABLE products (
sku VARCHAR(5),
quantity INTEGER
);
-- SQLite stores this row; other databases reject it with an error
INSERT INTO products VALUES ('LAMP-001', 'twelve');
SELECT sku, quantity FROM products;
-- Output (SQLite):
-- sku | quantity
-- ---------+---------
-- LAMP-001 | twelve
-
Deklariere einen Fremdschlüssel in einer eigenen
FOREIGN KEY-Zeile, nicht alsREFERENCESinnerhalb der Spaltendefinition: MySQL 8 akzeptiert diese Kurzform und ignoriert sie dann. SQLite erzwingt Fremdschlüssel erst nachPRAGMA foreign_keys = ON;, das du bei jeder Verbindung ausführst. -
CREATE TABLE schlägt fehl, wenn die Tabelle bereits existiert. Schreib stattdessen
CREATE TABLE IF NOT EXISTS, um sie zu überspringen. -
In MySQL kann eine
TEXT-Spalte keinDEFAULToderUNIQUEhaben. VerwendeVARCHAR(n), wie in den Beispielen hier.
Alternative Syntax
Automatisch nummerierte IDs werden in jeder Datenbank anders geschrieben:
| Datenbank | Automatisch nummerierte ID-Spalte |
|---|---|
| PostgreSQL | id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY |
| MySQL | id INT AUTO_INCREMENT PRIMARY KEY |
| SQLite | id INTEGER PRIMARY KEY |
| SQL Server | id INT IDENTITY(1,1) PRIMARY KEY |
Lass die ID bei einem Insert weg, und die Datenbank trägt die nächste Nummer ein.
SQL Server hat außerdem eigene Namen für Wahr/Falsch- und Datum-Zeit-Spalten und kein IF NOT EXISTS. Verwende BIT (mit 1 und 0) statt BOOLEAN, DATETIME2 für Datum und Uhrzeit (sein TIMESTAMP ist eine Zeilenversionsnummer, kein Datum) und prüfe OBJECT_ID, bevor du die Tabelle erstellst:
-- SQL Server
IF OBJECT_ID('users', 'U') IS NULL
CREATE TABLE users (
id INT IDENTITY(1,1) PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
is_active BIT NOT NULL DEFAULT 1,
created_at DATETIME2 NOT NULL DEFAULT CURRENT_TIMESTAMP
);
Wann solltest du CREATE TABLE verwenden?
Jede Tabelle beginnt mit CREATE TABLE, aber die Spalten und Constraints, die du wählst, lösen unterschiedliche Probleme.
Eine neue Art von Daten speichern
Jede Art von Objekt, die deine Anwendung verwaltet, etwa Kunden, Bücher oder Rechnungen, bekommt eine eigene Tabelle, mit einer Spalte für jede Eigenschaft und einem Typ, der zu den Werten passt.
Jeder Zeile eine eindeutige ID geben
Ein PRIMARY KEY verhindert, dass sich zwei Zeilen eine Kennung teilen, sodass du immer genau eine Zeile finden, aktualisieren oder verknüpfen kannst. Lass die Datenbank die Zeilen nummerieren (siehe „Alternative Syntax“ oben) oder kombiniere zwei Spalten, wenn ein Wertepaar nötig ist, um eine Zeile zu identifizieren.
Fehlerhafte oder fehlende Daten fernhalten
Constraints lehnen Zeilen ab, die deine Regeln verletzen: NOT NULL für Pflichtspalten, UNIQUE für Werte wie E-Mail-Adressen und CHECK für erlaubte Wertebereiche. DEFAULT füllt eine Spalte, die ein Insert weglässt.
Zusammengehörige Tabellen verknüpfen
Ein FOREIGN KEY lässt eine Spalte auf eine Zeile in einer anderen Tabelle verweisen, sodass eine Bestellung keinen Kunden nennen kann, der nicht existiert. Mit ON DELETE CASCADE löscht das Entfernen der übergeordneten Zeile auch die Zeilen, die auf sie verweisen.
Abfrageergebnisse als Tabelle speichern
CREATE TABLE ... AS SELECT erstellt eine Tabelle und füllt sie in einer einzigen Anweisung aus einer Abfrage. Nutze es für Snapshots, Report-Tabellen oder ein Backup von Zeilen, die du gleich ändern willst.
Praxisbeispiele für CREATE TABLE
Die Fehlermeldungen stammen von PostgreSQL. Andere Datenbanken lehnen dieselben Zeilen mit eigenem Wortlaut ab.
Eine Verknüpfungstabelle mit zweispaltigem Schlüssel
Studierende belegen viele Kurse, und Kurse haben viele Studierende. Die Tabelle enrollments verknüpft sie, und ihr Primärschlüssel ist das ID-Paar, sodass sich jemand für viele Kurse einschreiben kann, aber nicht zweimal für denselben:
CREATE TABLE enrollments (
student_id INTEGER NOT NULL,
course_id INTEGER NOT NULL,
enrolled_on DATE,
PRIMARY KEY (student_id, course_id)
);
INSERT INTO enrollments VALUES (1, 101, '2026-09-01');
INSERT INTO enrollments VALUES (1, 102, '2026-09-01');
INSERT INTO enrollments VALUES (1, 101, '2026-09-08');
-- ERROR: duplicate key value violates unique constraint "enrollments_pkey"
-- DETAIL: Key (student_id, course_id)=(1, 101) already exists.
SELECT * FROM enrollments;
-- Output:
-- student_id | course_id | enrolled_on
-- -----------+-----------+------------
-- 1 | 101 | 2026-09-01
-- 1 | 102 | 2026-09-01
Anmeldungen, die die Regeln einhalten
Jedes Konto braucht eine E-Mail-Adresse, die kein anderes Konto verwendet, und mindestens einen Platz. Neue Konten starten im kostenlosen Tarif mit einem Platz:
CREATE TABLE accounts (
id INTEGER PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
tier VARCHAR(20) NOT NULL DEFAULT 'free',
seats INTEGER NOT NULL DEFAULT 1 CHECK (seats > 0)
);
INSERT INTO accounts (id, email) VALUES (1, 'sam@example.com');
SELECT * FROM accounts;
-- Output:
-- id | email | tier | seats
-- ---+-----------------+------+------
-- 1 | sam@example.com | free | 1
INSERT INTO accounts (id, email) VALUES (2, 'sam@example.com');
-- ERROR: duplicate key value violates unique constraint "accounts_email_key"
INSERT INTO accounts (id, email, seats) VALUES (3, 'kim@example.com', 0);
-- ERROR: new row ... violates check constraint "accounts_seats_check"
INSERT INTO accounts (id) VALUES (4);
-- ERROR: null value in column "email" ... violates not-null constraint
Bestellungen, die zu einem Kunden gehören müssen
Jede Bestellung verweist auf einen Kunden. Der Fremdschlüssel lehnt eine Bestellung für einen nicht existierenden Kunden ab, und ON DELETE CASCADE entfernt die Bestellungen eines Kunden, wenn der Kunde gelöscht wird. In SQLite führst du zuerst PRAGMA foreign_keys = ON; aus.
CREATE TABLE customers (
id INTEGER PRIMARY KEY,
name VARCHAR(100) NOT NULL
);
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
customer_id INTEGER NOT NULL,
total DECIMAL(10,2),
FOREIGN KEY (customer_id) REFERENCES customers(id) ON DELETE CASCADE
);
-- Input: customers
-- id | name
-- ---+-----------
-- 1 | Ana Lima
-- 2 | Ben Okafor
-- Input: orders
-- id | customer_id | total
-- ---+-------------+------
-- 10 | 1 | 25.00
-- 11 | 1 | 60.00
-- 12 | 2 | 42.50
INSERT INTO orders VALUES (13, 99, 15.00);
-- ERROR: ... violates foreign key constraint "orders_customer_id_fkey"
-- DETAIL: Key (customer_id)=(99) is not present in table "customers".
DELETE FROM customers WHERE id = 1;
-- Output (orders after the DELETE):
-- id | customer_id | total
-- ---+-------------+------
-- 12 | 2 | 42.50
Ein Snapshot aktiver Kunden
Kopiere die Kunden, die dieses Jahr bestellt haben, in eine eigene Tabelle – für eine Kampagnenliste, die sich bei neuen Bestellungen nicht ändern soll:
-- Input: customers
-- customer_id | name | email | last_order_date
-- ------------+------------+-------------------+----------------
-- 1 | Ana Lima | ana@example.com | 2026-03-18
-- 2 | Ben Okafor | ben@example.com | 2025-11-02
-- 3 | Chloe Park | chloe@example.com | 2026-06-30
-- 4 | Dev Shah | dev@example.com | NULL
CREATE TABLE active_customers AS
SELECT customer_id, name, email
FROM customers
WHERE last_order_date >= '2026-01-01';
-- SQL Server has no CREATE TABLE ... AS. Use SELECT ... INTO:
SELECT customer_id, name, email
INTO active_customers
FROM customers
WHERE last_order_date >= '2026-01-01';
-- Output (active_customers):
-- customer_id | name | email
-- ------------+------------+------------------
-- 1 | Ana Lima | ana@example.com
-- 3 | Chloe Park | chloe@example.com
Die neue Tabelle übernimmt die Spalten, ihre Typen und die Zeilen, aber weder den Primärschlüssel noch andere Constraints. Füge sie bei Bedarf mit ALTER TABLE hinzu.
Weiterführende Artikel zu CREATE TABLE
In diesem Blog:
- SQL-Temp-Table-Guide: Tabellen, die nur so lange bestehen wie deine Session
- SQL ALTER TABLE add column: eine Tabelle nach dem Erstellen ändern
- Zusammengesetzte Primärschlüssel in SQL: Schlüssel aus mehr als einer Spalte
- Fremdschlüssel in PostgreSQL verwenden: Fremdschlüssel und ihre Löschaktionen im Detail
- Guide zu Datenbankbeziehungen: Tabellen entwerfen, die miteinander verknüpft sind
- SQL-INSERT-Anweisung: Zeilen in eine neue Tabelle einfügen
- SQL-Tabellengenerator: Erstelle eine CREATE TABLE-Anweisung im Browser, statt sie von Hand zu schreiben
Offizielle Dokumentation:
Beekeeper Studio ist eine kostenlose & quelloffene Datenbank-GUI
Das beste SQL-Abfrage- & Editor-Tool, das ich je benutzt habe. Es bietet alles, was ich zum Verwalten meiner Datenbank brauche. - ⭐⭐⭐⭐⭐ Mit
Beekeeper Studio ist schnell, intuitiv und einfach zu bedienen. Beekeeper unterstützt jede Menge Datenbanken und läuft hervorragend auf Windows, Mac und Linux.
Was Nutzer über Beekeeper Studio sagen
„Beekeeper Studio hat meinen alten SQL-Workflow komplett ersetzt. Es ist schnell, intuitiv und macht die Arbeit mit Datenbanken wieder angenehm.“
„Ich habe viele Datenbank-GUIs ausprobiert, aber Beekeeper findet die perfekte Balance zwischen Features und Einfachheit. Es funktioniert einfach.“