💾 Was ist eine Datenbank?
📖 Definition
Eine Datenbank (Database, DB) ist eine systematisch strukturierte Sammlung von Daten. Ein DBMS (Database Management System, Datenbankverwaltungssystem) ist Software, die Datenbanken erstellt, verwaltet und darauf zugreift. Datenbanken ermöglichen effiziente Datenspeicherung und -abfrage und erlauben mehreren Benutzern sicheren gleichzeitigen Zugriff.
🎯 Verstehen mit Analogie
Bibliothekssystem
Denken Sie an eine Datenbank als Bibliothek:
- Datenbank: Die gesamte Bibliothek
- Tabelle: Jeder Bereich (Fiktion, Wissenschaft, Geschichte, etc.)
- Zeile (Row): Einzelnes Buch
- Spalte (Column): Buchattribute (Titel, Autor, Erscheinungsjahr, etc.)
- Primärschlüssel (Primary Key): Eindeutige Buchnummer
- DBMS: Bibliothekar und Verwaltungssystem
Bibliothek (Datenbank)
├─ Fiktion-Bereich (Tabelle)
│ ├─ Buch 1: Harry Potter, J.K. Rowling, 1997
│ ├─ Buch 2: Der Herr der Ringe, Tolkien, 1954
│ └─ Buch 3: Der kleine Prinz, Saint-Exupéry, 1943
├─ Wissenschaft-Bereich (Tabelle)
│ ├─ Buch 1: Kosmos, Carl Sagan, 1980
│ └─ Buch 2: Das egoistische Gen, Richard Dawkins, 1976
└─ Ausleihprotokoll (Tabelle)
├─ Datensatz 1: Mitglied123, Harry Potter, 2024-01-15
└─ Datensatz 2: Mitglied456, Kosmos, 2024-01-20
⚙️ Funktionsweise
1. Datenbankstruktur
Datenbank (Database)
└─ Tabelle (Table)
├─ Zeile (Row/Record) - Einzelnes Datenelement
│ └─ Beispiel: Informationen eines Benutzers
└─ Spalte (Column/Field) - Datenattribute
└─ Beispiel: Name, E-Mail, Alter
2. Beispiel Relationale Datenbank
-- users-Tabelle
users
┌────┬────────┬──────────────────┬─────┐
│ id │ name │ email │ age │
├────┼────────┼──────────────────┼─────┤
│ 1 │ Max │ max@mail.com │ 25 │
│ 2 │ Anna │ anna@mail.com │ 30 │
│ 3 │ Peter │ peter@mail.com │ 28 │
└────┴────────┴──────────────────┴─────┘
-- orders-Tabelle
orders
┌────┬─────────┬─────────────┬───────┐
│ id │ user_id │ product │ price │
├────┼─────────┼─────────────┼───────┤
│ 1 │ 1 │ Laptop │ 1500 │
│ 2 │ 1 │ Maus │ 30 │
│ 3 │ 2 │ Tastatur │ 80 │
└────┴─────────┴─────────────┴───────┘
↑
└─ Fremdschlüssel: Referenziert id in users-Tabelle
3. CRUD-Operationen
CRUD sind die 4 grundlegenden Datenbankoperationen:
C - Create (Erstellen): Neue Daten hinzufügen
R - Read (Lesen): Daten abfragen
U - Update (Aktualisieren): Vorhandene Daten ändern
D - Delete (Löschen): Daten entfernen
💡 Echte Beispiele
CRUD mit SQL
-- CREATE (Erstellen): Tabelle erstellen
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
age INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- CREATE (Erstellen): Daten hinzufügen
INSERT INTO users (name, email, age)
VALUES ('Max', 'max@mail.com', 25);
INSERT INTO users (name, email, age)
VALUES
('Anna', 'anna@mail.com', 30),
('Peter', 'peter@mail.com', 28);
-- READ (Lesen): Alle Benutzer abfragen
SELECT * FROM users;
-- READ (Lesen): Bedingte Abfrage
SELECT name, email FROM users
WHERE age >= 28;
-- READ (Lesen): Sortierte Abfrage
SELECT * FROM users
ORDER BY age DESC;
-- READ (Lesen): Suche
SELECT * FROM users
WHERE name LIKE 'Max%';
-- UPDATE (Aktualisieren): Daten ändern
UPDATE users
SET age = 26
WHERE name = 'Max';
-- UPDATE (Aktualisieren): Mehrere Felder ändern
UPDATE users
SET email = 'new@mail.com', age = 31
WHERE id = 2;
-- DELETE (Löschen): Daten entfernen
DELETE FROM users
WHERE id = 3;
-- DELETE (Löschen): Bedingte Löschung
DELETE FROM users
WHERE age < 20;
Datenbanknutzung in Node.js
const mysql = require('mysql2/promise');
// Datenbankverbindung
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'password',
database: 'myapp',
waitForConnections: true,
connectionLimit: 10
});
// CREATE - Benutzer hinzufügen
async function createUser(name, email, age) {
const [result] = await pool.execute(
'INSERT INTO users (name, email, age) VALUES (?, ?, ?)',
[name, email, age]
);
console.log('Erstellte ID:', result.insertId);
return result.insertId;
}
// READ - Alle Benutzer abrufen
async function getAllUsers() {
const [rows] = await pool.execute('SELECT * FROM users');
return rows;
}
// READ - Bestimmten Benutzer abrufen
async function getUserById(id) {
const [rows] = await pool.execute(
'SELECT * FROM users WHERE id = ?',
[id]
);
return rows[0];
}
// UPDATE - Benutzerinformationen aktualisieren
async function updateUser(id, name, email, age) {
const [result] = await pool.execute(
'UPDATE users SET name = ?, email = ?, age = ? WHERE id = ?',
[name, email, age, id]
);
console.log('Aktualisierte Zeilen:', result.affectedRows);
return result.affectedRows;
}
// DELETE - Benutzer löschen
async function deleteUser(id) {
const [result] = await pool.execute(
'DELETE FROM users WHERE id = ?',
[id]
);
console.log('Gelöschte Zeilen:', result.affectedRows);
return result.affectedRows;
}
// Verwendungsbeispiel
async function main() {
try {
// Erstellen
const userId = await createUser('Max', 'max@mail.com', 25);
// Abfragen
const users = await getAllUsers();
console.log('Alle Benutzer:', users);
// Bestimmten Benutzer abfragen
const user = await getUserById(userId);
console.log('Bestimmter Benutzer:', user);
// Aktualisieren
await updateUser(userId, 'Max', 'new@mail.com', 26);
// Löschen
await deleteUser(userId);
} catch (error) {
console.error('Fehler:', error);
}
}
main();
ORM-Verwendung (Sequelize)
const { Sequelize, DataTypes } = require('sequelize');
// Datenbankverbindung
const sequelize = new Sequelize('myapp', 'root', 'password', {
host: 'localhost',
dialect: 'mysql'
});
// Modelldefinition (Tabellenstruktur)
const User = sequelize.define('User', {
name: {
type: DataTypes.STRING(50),
allowNull: false
},
email: {
type: DataTypes.STRING(100),
allowNull: false,
unique: true
},
age: {
type: DataTypes.INTEGER
}
});
// CRUD-Operationen (Ohne SQL, nur JavaScript!)
async function ormExample() {
// CREATE - Erstellen
const user = await User.create({
name: 'Max',
email: 'max@mail.com',
age: 25
});
console.log('Erstellt:', user.toJSON());
// READ - Abfragen
const allUsers = await User.findAll();
console.log('Alle Benutzer:', allUsers);
// READ - Bedingte Abfrage
const youngUsers = await User.findAll({
where: { age: { [Sequelize.Op.gte]: 20 } },
order: [['age', 'DESC']]
});
// READ - Einen abfragen
const oneUser = await User.findOne({
where: { email: 'max@mail.com' }
});
// UPDATE - Aktualisieren
await User.update(
{ age: 26 },
{ where: { name: 'Max' } }
);
// DELETE - Löschen
await User.destroy({
where: { id: 1 }
});
}
Beziehungseinstellung (JOIN)
// Beziehung zwischen Benutzer und Bestellungen einrichten
const User = sequelize.define('User', {
name: DataTypes.STRING,
email: DataTypes.STRING
});
const Order = sequelize.define('Order', {
product: DataTypes.STRING,
price: DataTypes.DECIMAL(10, 2)
});
// Beziehungsdefinition: Ein Benutzer kann mehrere Bestellungen haben
User.hasMany(Order);
Order.belongsTo(User);
// JOIN-Abfrage
async function getUserWithOrders(userId) {
const userWithOrders = await User.findOne({
where: { id: userId },
include: Order // JOIN
});
console.log(userWithOrders.toJSON());
// {
// id: 1,
// name: 'Max',
// email: 'max@mail.com',
// Orders: [
// { product: 'Laptop', price: 1500 },
// { product: 'Maus', price: 30 }
// ]
// }
}
🤔 Häufige Fragen
F1. Warum Datenbanken verwenden?
A: Viele Vorteile gegenüber Dateisystemen:
❌ Dateisystem (z.B.: users.txt)
├─ Mögliche Datenduplizierung
├─ Probleme beim gleichzeitigen Zugriff
├─ Schwierige Sicherung/Wiederherstellung
├─ Sicherheitslücken
└─ Langsame Suchen
✅ Datenbank
├─ Garantierte Datenintegrität
├─ Nebenläufigkeitskontrolle (mehrere Benutzer)
├─ Automatisierte Sicherung/Wiederherstellung
├─ Zugriffsverwaltung
├─ Schnelle Suchen (Indizes)
└─ Transaktionsunterstützung
F2. Welche Datenbank wählen?
A: Abhängig von den Projektanforderungen:
// Relationale Datenbanken (SQL)
MySQL / PostgreSQL / SQLite
├─ Vorteile: Präzise Datenstruktur, Transaktionen
├─ Nachteile: Geringe Flexibilität, begrenzte Skalierbarkeit
└─ Geeignet: Finanzen, E-Commerce, Benutzerverwaltung
// Nicht-relationale Datenbanken (NoSQL)
MongoDB / Redis / Cassandra
├─ Vorteile: Flexibles Schema, horizontale Skalierung
├─ Nachteile: Schwierige Behandlung komplexer Beziehungen
└─ Geeignet: Social Media, Echtzeitanalyse, Caching
F3. Was ist ein Index?
A: Eine Datenstruktur, die den Datenabruf beschleunigt:
-- Ohne Index
SELECT * FROM users WHERE email = 'test@mail.com';
-- → 1M Zeilen überprüfen (langsam)
-- Index erstellen
CREATE INDEX idx_email ON users(email);
-- Mit Index
SELECT * FROM users WHERE email = 'test@mail.com';
-- → Direkt über Index finden (schnell!)
-- Nachteil: Langsamere Schreibvorgänge (Index muss aktualisiert werden)
Analogie: Wie das Inhaltsverzeichnis oder der Index eines Buches, ermöglicht es, schnell zu finden, was Sie suchen.
F4. Was ist eine Transaktion?
A: Mehrere Operationen als eine Einheit bündeln:
// Banküberweisungsbeispiel
async function transferMoney(fromId, toId, amount) {
const connection = await pool.getConnection();
try {
// Transaktion starten
await connection.beginTransaction();
// 1. Saldo des Absenders verringern
await connection.execute(
'UPDATE accounts SET balance = balance - ? WHERE id = ?',
[amount, fromId]
);
// 2. Saldo des Empfängers erhöhen
await connection.execute(
'UPDATE accounts SET balance = balance + ? WHERE id = ?',
[amount, toId]
);
// Alles erfolgreich → Bestätigen
await connection.commit();
console.log('Überweisung abgeschlossen!');
} catch (error) {
// Fehler → Alles rückgängig machen
await connection.rollback();
console.log('Überweisung fehlgeschlagen, zurückgesetzt');
throw error;
} finally {
connection.release();
}
}
// ACID-Prinzipien
// Atomicity (Atomarität): Alles oder nichts
// Consistency (Konsistenz): Keine Regelverletzung
// Isolation (Isolation): Unabhängigkeit zwischen Transaktionen
// Durability (Dauerhaftigkeit): Permanente Speicherung nach Abschluss
F5. Was ist SQL Injection?
A: Ein Angriff, der bösartigen SQL-Code einschleust:
// ❌ Gefährlicher Code (anfällig für SQL Injection)
const email = req.body.email; // "admin@mail.com' OR '1'='1"
const query = `SELECT * FROM users WHERE email = '${email}'`;
// Führt aus: SELECT * FROM users WHERE email = 'admin@mail.com' OR '1'='1'
// → Alle Benutzerinformationen durchgesickert!
// ✅ Sicherer Code (Prepared Statement)
const [rows] = await pool.execute(
'SELECT * FROM users WHERE email = ?',
[email] // Automatisch maskiert
);
// ORM-Verwendung (automatische Abwehr)
const user = await User.findOne({
where: { email: email } // Sicher
});
🎓 Nächste Schritte
Nachdem Sie Datenbanken verstanden haben, lernen Sie:
- SQL vs NoSQL - Datenbank-Auswahlhandbuch
- Was ist Node.js? - Backend-Entwicklung
- Was ist eine API? - Verbindung zwischen Datenbank und Frontend
Praktische Übung
# MySQL Installation und Ausführung
brew install mysql # macOS
sudo apt install mysql # Linux
# Datenbankverbindung
mysql -u root -p
# Datenbank erstellen
CREATE DATABASE myapp;
USE myapp;
# Tabelle erstellen und Daten hinzufügen
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50),
email VARCHAR(100)
);
INSERT INTO users (name, email) VALUES ('Max', 'test@mail.com');
SELECT * FROM users;
🎬 Zusammenfassung
Datenbanken sind der Kern aller Anwendungen:
- Datenbank: Strukturierte Datensammlung
- CRUD: Create, Read, Update, Delete - Grundoperationen
- Tabelle: Organisiert Daten in Zeilen und Spalten
- Beziehung: Verbindungen zwischen Tabellen (JOIN)
- Transaktion: Sichere Datenverarbeitung
Ein gutes Verständnis von Datenbanken ermöglicht den Aufbau stabiler und skalierbarer Anwendungen! 💾✨