Die Wahl des Datentyps ist wie die Wahl des richtigen Werkzeugs. Du würdest ja auch keinen Schraubenzieher nehmen, um einen Nagel einzuschlagen (hoffentlich). Genauso in der Datenbank: Der richtige Datentyp hat großen Einfluss auf Performance, Speicherverbrauch und wie easy du mit den Daten arbeiten kannst. Zum Beispiel: Wenn wir Geld als REAL speichern, kann es zu Genauigkeitsproblemen kommen, und wenn du TEXT statt VARCHAR für kurze Strings nimmst, verbraucht die DB mehr Speicher.
Beim Auswählen des Datentyps solltest du auf ein paar Sachen achten:
Charakter der Daten
Überleg dir, zu welcher Kategorie die Daten gehören: Zahlen, Strings, boolsche Werte, Datumsangaben oder was Komplexeres wie JSON-Strukturen.
Datenmenge
Wie viel willst du speichern? Für Texte bis 50 Zeichen nimm lieber VARCHAR(50) statt TEXT.
Genauigkeit und Wertebereich
Brauchst du hohe Genauigkeit (z.B. für Finanzberechnungen)? Willst du den Wertebereich einschränken?
Häufigkeit und Art der Abfragen
Wie oft greifst du auf die Daten zu? Komplexe Typen wie JSONB brauchen mehr Ressourcen beim Verarbeiten.
Beispiele für die Auswahl von Datentypen
Unterschiedliche Daten – unterschiedliche Anforderungen. Manchmal zählt jeder Cent, manchmal reicht es, wenn einfach alles reinpasst. Hier ein paar Beispiele, wie du den passenden Datentyp für eine bestimmte Situation findest.
Finanzdaten
Wenn es ums Speichern von Geld geht, wie in der Buchhaltung, sind Fehler ein No-Go. Am besten nimmst du NUMERIC, das ist super genau. Zum Beispiel wollen wir eine Tabelle mit diesen Spalten:
| Spaltenname | Datentyp | Kommentar |
|---|---|---|
| id | SERIAL | Primärschlüssel |
| amount | NUMERIC(10, 2) | Zehn Stellen, davon zwei nach dem Komma |
| currency_code | CHAR(3) | ISO-Währungscode, z.B. "USD", "EUR" |
| transaction_date | TIMESTAMP | Transaktionszeit, Standard ist aktuelle Zeit |
Warum nicht REAL? Weil Gleitkommazahlen ungenau werden können – und das ist bei Finanzen kritisch.
Textdaten
Wenn du Usernamen, Adressen oder andere Strings speicherst, gib immer die maximale Länge an, wenn möglich. Zum Beispiel VARCHAR(50) statt TEXT. Das hilft Fehler zu vermeiden und spart Speicher.
| Spaltenname | Datentyp | Kommentar |
|---|---|---|
| id | SERIAL | Primärschlüssel |
| username | VARCHAR(50) | User-Login, eindeutig und Pflichtfeld |
| VARCHAR(255) | E-Mail-Adresse | |
| bio | TEXT | Bio, kann lang sein |
Wenn die String-Länge fest ist (z.B. zweistellige Ländercodes), nimm CHAR:
| Spaltenname | Datentyp | Kommentar |
|---|---|---|
| code | CHAR(2) | ISO-Ländercode (z.B. "US"), Primärschlüssel |
| name | VARCHAR(100) | Ländername, Pflichtfeld |
Daten für Zeitstempel
Um Eventzeiten oder Zeitpläne zu speichern, ist TIMESTAMP meistens die beste Wahl, weil es Datum und Uhrzeit zusammen enthält.
| Spaltenname | Datentyp | Kommentar |
|---|---|---|
| id | SERIAL | Primärschlüssel |
| event_name | VARCHAR(100) | Eventname |
| start_time | TIMESTAMP | Startzeit des Events, Pflichtfeld |
| end_time | TIMESTAMP | Endzeit des Events, Pflichtfeld |
Brauchst du nur die Uhrzeit ohne Datum, nimm TIME, und nur das Datum ohne Uhrzeit – DATE.
Eindeutige IDs
Wenn du IDs brauchst, die weltweit eindeutig sind, nimm UUID. Zum Beispiel für eine eindeutige Transaktions-ID:
| Spaltenname | Datentyp | Kommentar |
|---|---|---|
| request_id | UUID | Eindeutige Anfrage-ID, wird standardmäßig mit gen_random_uuid() generiert |
| endpoint | VARCHAR(255) | Adresse des API-Endpoints |
| timestamp | TIMESTAMP | Anfragezeit, Standard ist aktuelle Zeit |
JSONB: Komplexe Strukturen
Wenn du Daten speichern willst, deren Struktur sich ändern kann oder komplex ist, z.B. User-Einstellungen oder Metadaten, nimm JSONB.
| Spaltenname | Datentyp | Kommentar |
|---|---|---|
| user_id | SERIAL | Primärschlüssel (User-ID) |
| preferences | JSONB | User-Einstellungen im JSON-Format |
Mit JSONB kannst du easy arbeiten, aber denk dran: Bei vielen Inserts/Updates kann das auf die Performance gehen.
Arrays
Arrays sind praktisch, wenn du Listen mit gleichartigen Daten speichern willst. Zum Beispiel eine Liste von Tags:
| Spaltenname | Datentyp | Kommentar |
|---|---|---|
| id | SERIAL | Primärschlüssel |
| title | VARCHAR(255) | Artikelüberschrift |
| tags | TEXT[] | Tag-Array |
Überblick: Datentypen nach Aufgabe
| Aufgabentyp | Empfohlener Datentyp | Beispiel |
|---|---|---|
| Datensatz-ID | SERIAL, BIGSERIAL, UUID |
id SERIAL PRIMARY KEY |
| Anzahl, ganze Zahlen | INTEGER, BIGINT |
quantity INTEGER |
| Finanzberechnungen | NUMERIC |
price NUMERIC(10, 2) |
| Strings speichern | VARCHAR(n), TEXT |
username VARCHAR(50) |
| Kurz, feste Strings | CHAR(n) |
status CHAR(1) |
| Datum und Zeit | DATE, TIME, TIMESTAMP |
created_at TIMESTAMP DEFAULT NOW() |
| Eindeutige IDs | UUID |
id UUID PRIMARY KEY DEFAULT gen_random_uuid() |
| Komplexe Strukturen (JSON) | JSONB |
metadata JSONB |
| Listen von Werten | ARRAY |
tags TEXT[] |
| Boolescher Wert | BOOLEAN |
is_active BOOLEAN |
Du kennst wahrscheinlich schon alle Typen außer SERIAL. Das Ding ist: SERIAL ist eigentlich nur ein INTEGER, der als ID für Zeilen in Tabellen genutzt wird.
Er wird automatisch bei jedem neuen Eintrag um 1 erhöht. Wenn du also 10 Zeilen einfügst, hat die erste Zeile id = 1, die zweite = 2 usw. Mehr dazu gibt's in der nächsten Vorlesung :)
GO TO FULL VERSION