better-sqlite3-typescript für TypeScript: Komplettguide mit Beispielen
In der TypeScript-Entwicklung stellt sich oft die Frage nach einer lokalen Datenspeicherung, ohne eine vollwertige Datenbank aufsetzen zu müssen. SQLite ist hier die ideale Lösung: eine eingebettete, relationale Datenbank, die ohne separaten Server auskommt. Die Standardbibliothek better-sqlite3 ist jedoch in JavaScript geschrieben und bietet keine integrierte Typisierung. Hier kommt better-sqlite3-typescript ins Spiel – ein Wrapper, der strikte TypeScript-Typisierung über die synchrone API von better-sqlite3 legt.
Diese Bibliothek ermöglicht es Ihnen, typsicheren Code für die Arbeit mit SQLite zu schreiben. Sie profitieren von Autovervollständigung in der IDE, Typprüfung zur Kompilierzeit und einer Reduzierung von Laufzeitfehlern. Sie erhalten alle Vorteile des synchronen Datenbankzugriffs (Einfachheit, Vorhersagbarkeit, hohe Leistung) kombiniert mit der Stärke des TypeScript-Typsystems.
In diesem Artikel gehen wir detailliert auf die Installation, die wichtigsten Methoden ein, zeigen praxisnahe Beispiele und geben Tipps zur Performance. Der Inhalt richtet sich sowohl an Einsteiger als auch an erfahrene Entwickler, die SQLite effizient in ihren TypeScript-Projekten einsetzen möchten.
Installation
Führen Sie zur Installation der Bibliothek folgenden Befehl im Terminal Ihres Projekts aus:
npm install better-sqlite3-typescript better-sqlite3
Zusätzlich müssen die Typen für TypeScript installiert werden:
npm install -D @types/better-sqlite3
Nach der Installation können Sie die Bibliothek in Ihr Projekt importieren:
import Database from 'better-sqlite3-typescript';
Schnellstart
Ein minimales funktionsfähiges Beispiel zum Erstellen einer Datenbank, Anlegen einer Tabelle und Einfügen von Daten:
import Database from 'better-sqlite3-typescript';
// Datenbank erstellen oder öffnen
const db = new Database('my_database.db');
// Tabelle erstellen
db.exec(`
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
age INTEGER
)
`);
// Daten einfügen
const insert = db.prepare('INSERT INTO users (name, email, age) VALUES (?, ?, ?)');
insert.run('Alice', 'alice@example.com', 30);
insert.run('Bob', 'bob@example.com', 25);
// Daten lesen
const select = db.prepare('SELECT * FROM users');
const users = select.all();
console.log(users);
// Verbindung schließen
db.close();
Dieser Code erstellt die Datei my_database.db im aktuellen Verzeichnis, legt die Tabelle users an, fügt zwei Benutzer hinzu und gibt sie in der Konsole aus.
Wichtige Methoden und Funktionen
Sehen wir uns die wichtigsten Methoden der Bibliothek an. Alle Beispiele gehen davon aus, dass Sie bereits eine Datenbankinstanz db haben.
1. new Database(filename, options?)
Signatur: new Database(filename: string, options?: DatabaseOptions): Database
Beschreibung: Erstellt oder öffnet eine SQLite-Datenbank. Wenn die Datei nicht existiert, wird sie angelegt. Optionen erlauben die Konfiguration des Öffnungsmodus (readonly, memory usw.).
Beispiel:
// Datenbank im Arbeitsspeicher öffnen (wird nicht auf die Festplatte geschrieben)
const memDb = new Database(':memory:');
// Datenbank im Nur-Lesen-Modus öffnen
const readOnlyDb = new Database('data.db', { readonly: true });
2. db.prepare(sql)
Signatur: prepare(sql: string): Statement
Beschreibung: Kompiliert eine SQL-Abfrage in ein vorbereitetes Statement. Gibt ein Statement-Objekt zurück, das mehrfach mit verschiedenen Parametern ausgeführt werden kann.
Beispiel:
const stmt = db.prepare('SELECT * FROM users WHERE age > ?');
const adults = stmt.all(18);
console.log(adults);
3. statement.run(...params)
Signatur: run(...params: BindParameters): RunResult
Beschreibung: Führt das vorbereitete Statement aus. Gibt ein Objekt mit changes (Anzahl der betroffenen Zeilen) und lastInsertRowid (ID der zuletzt eingefügten Zeile) zurück.
Beispiel:
const insert = db.prepare('INSERT INTO users (name, email) VALUES (?, ?)');
const result = insert.run('Charlie', 'charlie@example.com');
console.log(`Neue Benutzer-ID: ${result.lastInsertRowid}`);
4. statement.get(...params)
Signatur: get(...params: BindParameters): T | undefined
Beschreibung: Führt das Statement aus und gibt die erste Ergebniszeile als Objekt zurück. Wenn keine Zeile gefunden wird, wird undefined zurückgegeben.
Beispiel:
const select = db.prepare('SELECT * FROM users WHERE id = ?');
const user = select.get(1);
console.log(user); // { id: 1, name: 'Alice', email: 'alice@example.com', age: 30 }
5. statement.all(...params)
Signatur: all(...params: BindParameters): T[]
Beschreibung: Führt das Statement aus und gibt alle Ergebniszeilen als Array von Objekten zurück.
Beispiel:
const selectAll = db.prepare('SELECT * FROM users');
const allUsers = selectAll.all();
console.log(allUsers); // Array aller Benutzer
6. db.exec(sql)
Signatur: exec(sql: string): void
Beschreibung: Führt einen oder mehrere SQL-Befehle aus, die keine Ergebniszeilen zurückgeben (z. B. CREATE TABLE, INSERT, UPDATE, DELETE). Ideal für Schemaänderungen oder Batch-Operationen.
Beispiel:
db.exec(`
CREATE TABLE IF NOT EXISTS products (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
price REAL NOT NULL
)
`);
7. db.transaction(fn)
Signatur: transaction(fn: (...args: any[]) => any): (...args: any[]) => any
Beschreibung: Erstellt eine Transaktion aus einer Funktion. Alle Datenbankoperationen innerhalb der Funktion werden entweder vollständig oder gar nicht ausgeführt. Dies verbessert die Performance bei mehreren Schreiboperationen und stellt die Datenintegrität sicher.
Beispiel:
const insertMany = db.transaction((users: { name: string; email: string }[]) => {
for (const user of users) {
db.prepare('INSERT INTO users (name, email) VALUES (?, ?)').run(user.name, user.email);
}
});
insertMany([
{ name: 'David', email: 'david@example.com' },
{ name: 'Eva', email: 'eva@example.com' }
]);
8. db.close()
Signatur: close(): void
Beschreibung: Schließt die Datenbankverbindung. Nach dem Schließen können keine weiteren Operationen auf der Datenbank ausgeführt werden.
Beispiel:
db.close();
Typisierung und TypeScript-Vorteile
Der größte Vorteil von better-sqlite3-typescript ist die nahtlose Integration mit TypeScript. Sie können benutzerdefinierte Typen für Ihre Abfragen definieren:
interface User {
id: number;
name: string;
email: string;
age: number | null;
}
const stmt = db.prepare('SELECT * FROM users WHERE id = ?');
const user = stmt.get(1);
// user ist automatisch vom Typ User | undefined
console.log(user?.name); // TypeScript erkennt das optional chaining
Durch die Generics erhalten Sie automatische Typinferenz und vermeiden Laufzeitfehler durch falsche Datentypen.
Performance-Tipps
- Verwenden Sie Transaktionen: Fassen Sie mehrere Schreiboperationen in einer Transaktion zusammen. Dies reduziert den I/O-Overhead erheblich.
- Nutzen Sie prepared Statements: Bereiten Sie SQL-Abfragen einmal vor und führen Sie sie mehrfach mit verschiedenen Parametern aus. Das spart Kompilierungszeit.
- Indexierung: Erstellen Sie Indizes für Spalten, die häufig in WHERE-Klauseln verwendet werden.
- Vermeiden Sie
db.execfür SELECT-Abfragen: Verwenden Sie stattdessendb.prepareund die entsprechenden Methoden (get,all).
Fazit
better-sqlite3-typescript ist eine leistungsstarke und benutzerfreundliche Bibliothek für die Arbeit mit SQLite in TypeScript-Projekten. Sie kombiniert die Einfachheit und Geschwindigkeit der synchronen better-sqlite3-API mit den Vorteilen eines starken Typsystems. Ob für kleine Anwendungen, Prototypen oder eingebettete Systeme – diese Bibliothek ist eine ausgezeichnete Wahl.
Probieren Sie es selbst aus: Installieren Sie die Bibliothek, experimentieren Sie mit den Beispielen aus diesem Guide und integrieren Sie SQLite typensicher in Ihr nächstes TypeScript-Projekt!
Auch in der Bibliothek
Arbeiten mit CSV in C++: Bibliotheken und Codebeispiele
WireMock.Net für C# (.NET): Vollständiges Tutorial & Anleitung
JSON-Verarbeitung in Swift: Codable, JSONSerialization und praktische Beispiele
Arbeiten mit Markdown in Java: Bibliotheken, Parser und Beispiele