Zum Inhalt springen

SQLite-Erweiterung

Die SQLite-Erweiterung ermöglicht DuckDB, Daten direkt aus einer SQLite-Datenbankdatei zu lesen und zu schreiben. Die Daten können direkt aus den zugrunde liegenden SQLite-Tabellen abgefragt werden. Daten können aus SQLite-Tabellen in DuckDB-Tabellen geladen werden oder umgekehrt.

Installation und Laden

Die sqlite-Erweiterung wird beim ersten Gebrauch transparent aus dem offiziellen Erweiterungs-Repository automatisch geladen. Wenn Sie sie manuell installieren und laden möchten, führen Sie aus:

INSTALL sqlite;
LOAD sqlite;

Verwendung

Damit eine SQLite-Datei für DuckDB zugänglich ist, verwenden Sie die Anweisung ATTACH mit dem Typ sqlite oder sqlite_scanner. Angehängte SQLite-Datenbanken unterstützen Lese- und Schreiboperationen.

Um sich beispielsweise mit der Datei sakila.db zu verbinden, führen Sie aus:

ATTACH 'sakila.db' (TYPE sqlite);
USE sakila;

Die Tabellen in der Datei können gelesen werden, als wären sie normale DuckDB-Tabellen, die zugrunde liegenden Daten werden jedoch zur Abfragezeit direkt aus den SQLite-Tabellen in der Datei gelesen.

SHOW TABLES;
name
actor
address
category
city
country
customer
customer_list
film
film_actor
film_category
film_list
film_text
inventory
language
payment
rental
sales_by_film_category
sales_by_store
staff
staff_list
store

Sie können die Tabellen mit SQL abfragen, z. B. mit den Beispielabfragen aus sakila-examples.sql:

SELECT
cat.name AS category_name,
sum(ifnull(pay.amount, 0)) AS revenue
FROM category cat
LEFT JOIN film_category flm_cat
ON cat.category_id = flm_cat.category_id
LEFT JOIN film fil
ON flm_cat.film_id = fil.film_id
LEFT JOIN inventory inv
ON fil.film_id = inv.film_id
LEFT JOIN rental ren
ON inv.inventory_id = ren.inventory_id
LEFT JOIN payment pay
ON ren.rental_id = pay.rental_id
GROUP BY cat.name
ORDER BY revenue DESC
LIMIT 5;

Datentypen

SQLite ist ein schwach typisiertes Datenbanksystem. Beim Speichern von Daten in einer SQLite-Tabelle werden Typen daher nicht erzwungen. Das folgende SQL ist in SQLite gültig:

CREATE TABLE numbers (i INTEGER);
INSERT INTO numbers VALUES ('hello');

DuckDB ist ein stark typisiertes Datenbanksystem und verlangt daher, dass alle Spalten definierte Typen haben; das System prüft Daten rigoros auf Korrektheit.

Beim Abfragen von SQLite muss DuckDB eine konkrete Spaltentypzuordnung ableiten. DuckDB folgt den Type-Affinity-Regeln von SQLite mit einigen Erweiterungen.

  1. Enthält der deklarierte Typ den String INT, wird er in den Typ BIGINT übersetzt
  2. Enthält der deklarierte Typ der Spalte einen der Strings CHAR, CLOB oder TEXT, wird er in VARCHAR übersetzt.
  3. Enthält der deklarierte Typ einer Spalte den String BLOB oder ist kein Typ angegeben, wird er in BLOB übersetzt.
  4. Enthält der deklarierte Typ einer Spalte einen der Strings REAL, FLOA, DOUB, DEC oder NUM, wird er in DOUBLE übersetzt.
  5. Ist der deklarierte Typ DATE, wird er in DATE übersetzt.
  6. Enthält der deklarierte Typ den String TIME, wird er in TIMESTAMP übersetzt.
  7. Trifft nichts der oben genannten zu, wird er in VARCHAR übersetzt.

Da DuckDB erzwingt, dass die entsprechenden Spalten nur korrekt typisierte Werte enthalten, können wir den String „hello“ nicht in eine Spalte vom Typ BIGINT laden. Beim Lesen aus der Tabelle „numbers“ oben wird daher ein Fehler geworfen:

Terminal window
Mismatch Type Error: Invalid type in column "i": column was declared as integer, found "hello" of type "text" instead.

Dieser Fehler kann vermieden werden, indem die Option sqlite_all_varchar gesetzt wird:

SET GLOBAL sqlite_all_varchar = true;

Wenn gesetzt, überschreibt diese Option die oben beschriebenen Typkonvertierungsregeln und konvertiert die SQLite-Spalten stattdessen immer in eine VARCHAR-Spalte. Beachten Sie, dass diese Einstellung vor dem Aufruf von sqlite_attach gesetzt werden muss.

SQLite-Datenbanken direkt öffnen

SQLite-Datenbanken können auch direkt geöffnet und transparent anstelle einer DuckDB-Datenbankdatei verwendet werden. In jedem Client kann beim Verbinden ein Pfad zu einer SQLite-Datenbankdatei angegeben werden, woraufhin die SQLite-Datenbank geöffnet wird.

Mit der Shell kann eine SQLite-Datenbank beispielsweise wie folgt geöffnet werden:

Terminal window
duckdb sakila.db
SELECT first_name
FROM actor
LIMIT 3;
first_name
PENELOPE
NICK
ED

Daten nach SQLite schreiben

Zusätzlich zum Lesen von Daten aus SQLite ermöglicht die Erweiterung das Erstellen neuer SQLite-Datenbankdateien, das Erstellen von Tabellen, das Laden von Daten in SQLite und andere Änderungen an SQLite-Datenbankdateien mit Standard-SQL-Abfragen.

Damit können Sie DuckDB beispielsweise verwenden, um in einer SQLite-Datenbank gespeicherte Daten nach Parquet zu exportieren oder Daten aus einer Parquet-Datei in SQLite zu lesen.

Nachfolgend ein kurzes Beispiel, wie Sie eine neue SQLite-Datenbank erstellen und Daten darin laden.

ATTACH 'new_sqlite_database.db' AS sqlite_db (TYPE sqlite);
CREATE TABLE sqlite_db.tbl (id INTEGER, name VARCHAR);
INSERT INTO sqlite_db.tbl VALUES (42, 'DuckDB');

Die resultierende SQLite-Datenbank kann dann aus SQLite gelesen werden.

Terminal window
sqlite3 new_sqlite_database.db
SQLite version 3.39.5 2022-10-14 20:58:05
sqlite> SELECT * FROM tbl;
id name
-- ------
42 DuckDB

Viele Operationen auf SQLite-Tabellen werden unterstützt. Alle diese Operationen ändern die SQLite-Datenbank direkt, und das Ergebnis nachfolgender Operationen kann dann mit SQLite gelesen werden.

Nebenläufigkeit

DuckDB kann eine SQLite-Datenbank lesen oder ändern, während DuckDB oder SQLite dieselbe Datenbank aus einem anderen Thread oder einem separaten Prozess liest oder ändert. Mehr als ein Thread oder Prozess kann die SQLite-Datenbank gleichzeitig lesen, aber nur ein einzelner Thread oder Prozess kann zu einem Zeitpunkt in die Datenbank schreiben. Die Datenbanksperre wird von der SQLite-Bibliothek verwaltet, nicht von DuckDB. Innerhalb desselben Prozesses verwendet SQLite Mutexes. Beim Zugriff aus verschiedenen Prozessen verwendet SQLite Dateisystemsperren. Die Sperrmechanismen hängen auch von der SQLite-Konfiguration ab, etwa vom WAL-Modus. Weitere Informationen finden Sie in der SQLite-Dokumentation zu Locking.

Warning Das Linken mehrerer Kopien der SQLite-Bibliothek in dieselbe Anwendung kann zu Anwendungsfehlern führen. Weitere Informationen finden Sie in sqlite_scanner Issue #82.

Einstellungen

Die Erweiterung stellt die folgenden Konfigurationsparameter bereit.

Name Beschreibung Standard
sqlite_debug_show_queries DEBUG-EINSTELLUNG: alle an SQLite gesendeten Abfragen auf stdout ausgeben false

Unterstützte Operationen

Nachfolgend eine Liste unterstützter Operationen.

CREATE TABLE

CREATE TABLE sqlite_db.tbl (id INTEGER, name VARCHAR);

INSERT INTO

INSERT INTO sqlite_db.tbl VALUES (42, 'DuckDB');

SELECT

SELECT * FROM sqlite_db.tbl;
id name
42 DuckDB

COPY

COPY sqlite_db.tbl TO 'data.parquet';
COPY sqlite_db.tbl FROM 'data.parquet';

UPDATE

UPDATE sqlite_db.tbl SET name = 'Woohoo' WHERE id = 42;

DELETE

DELETE FROM sqlite_db.tbl WHERE id = 42;

ALTER TABLE

ALTER TABLE sqlite_db.tbl ADD COLUMN k INTEGER;

DROP TABLE

DROP TABLE sqlite_db.tbl;

CREATE VIEW

CREATE VIEW sqlite_db.v1 AS SELECT 42;

Transaktionen

CREATE TABLE sqlite_db.tmp (i INTEGER);
BEGIN;
INSERT INTO sqlite_db.tmp VALUES (42);
SELECT * FROM sqlite_db.tmp;
i
42
ROLLBACK;
SELECT * FROM sqlite_db.tmp;
i

Deprecated Die alte Funktion sqlite_attach ist veraltet. Es wird empfohlen, auf die neue ATTACH-Syntax umzusteigen.

Kompatibilität

Die SQLite-Erweiterung kann Datenbanken lesen, die von Turso geschrieben wurden, einer Rust-Neuimplementierung von SQLite.