⌘+k ctrl+k
1.4 (LTS)
搜索快捷键 cmd + k | ctrl + k
SQLite 扩展

SQLite 扩展允许 DuckDB 直接从 SQLite 数据库文件中读取和写入数据。可以直接对底层的 SQLite 表进行查询。数据可以从 SQLite 表加载到 DuckDB 表中,反之亦然。

安装和加载

sqlite 扩展在首次使用时会自动从官方扩展仓库自动加载。如果您想手动安装和加载它,请运行

INSTALL sqlite;
LOAD sqlite;

用法

要使 SQLite 文件可供 DuckDB 访问,请使用带有 sqlitesqlite_scanner 类型的 ATTACH 语句。挂载的 SQLite 数据库同时支持读写操作。

例如,要挂载 sakila.db 文件,请运行

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

文件中的表可以像普通 DuckDB 表一样被读取,但底层数据是在查询时直接从文件中的 SQLite 表读取的。

SHOW TABLES;
name
actor
address
category
城市
国家
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

您可以使用 SQL 查询这些表,例如使用 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;

数据类型

SQLite 是一个弱类型数据库系统。因此,在 SQLite 表中存储数据时,不会强制执行类型限制。以下是在 SQLite 中合法的 SQL

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

DuckDB 是一个强类型数据库系统,因此它要求所有列都必须定义类型,并严格检查数据的正确性。

在查询 SQLite 时,DuckDB 必须推导特定的列类型映射。DuckDB 遵循 SQLite 的类型亲和性规则,并进行了一些扩展。

  1. 如果声明的类型包含字符串 INT,则它会被转换为 BIGINT 类型。
  2. 如果列的声明类型包含字符串 CHARCLOBTEXT 中的任意一个,则它会被转换为 VARCHAR
  3. 如果列的声明类型包含字符串 BLOB,或者未指定类型,则它会被转换为 BLOB
  4. 如果列的声明类型包含字符串 REALFLOADOUBDECNUM 中的任意一个,则它会被转换为 DOUBLE
  5. 如果声明的类型是 DATE,则它会被转换为 DATE
  6. 如果声明的类型包含字符串 TIME,则它会被转换为 TIMESTAMP
  7. 如果上述条件均不适用,则它会被转换为 VARCHAR

由于 DuckDB 强制要求相应列仅包含正确类型的值,因此我们无法将字符串 “hello” 加载到类型为 BIGINT 的列中。因此,在读取上述 “numbers” 表时会抛出错误。

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

可以通过设置 sqlite_all_varchar 选项来避免此错误

SET GLOBAL sqlite_all_varchar = true;

设置此选项后,它将覆盖上述类型转换规则,并始终将 SQLite 列转换为 VARCHAR 列。请注意,必须在调用 sqlite_attach 之前 设置此项。

直接打开 SQLite 数据库

SQLite 数据库也可以直接打开,并可透明地替代 DuckDB 数据库文件使用。在任何客户端中连接时,都可以提供 SQLite 数据库文件的路径,系统将直接打开该 SQLite 数据库。

例如,在 shell 中,可以通过以下方式打开 SQLite 数据库

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

向 SQLite 写入数据

除了从 SQLite 读取数据外,该扩展还允许您使用标准 SQL 查询创建新的 SQLite 数据库文件、创建表、将数据摄入 SQLite 以及对 SQLite 数据库文件进行其他修改。

这使您能够利用 DuckDB 将存储在 SQLite 数据库中的数据导出为 Parquet 格式,或将 Parquet 文件中的数据读取到 SQLite 中。

以下是关于如何创建新 SQLite 数据库并将数据加载到其中的简要示例。

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');

由此生成的 SQLite 数据库随后可以从 SQLite 中读取。

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

支持对 SQLite 表执行多种操作。所有这些操作都会直接修改 SQLite 数据库,后续操作的结果随后可以使用 SQLite 进行读取。

并发

当 DuckDB 或 SQLite 从不同线程或独立进程读取或修改同一数据库时,DuckDB 均可读取或修改该 SQLite 数据库。多个线程或进程可以同时读取 SQLite 数据库,但同一时间只能有一个线程或进程写入该数据库。数据库锁定由 SQLite 库处理,而非 DuckDB。在同一进程内,SQLite 使用互斥锁(mutexes)。从不同进程访问时,SQLite 使用文件系统锁。锁定机制还取决于 SQLite 配置,例如 WAL 模式。有关详细信息,请参阅 SQLite 锁定文档

警告:在同一个应用程序中链接多个 SQLite 库副本可能会导致应用程序错误。有关更多信息,请参阅 sqlite_scanner Issue #82

设置

该扩展公开了以下配置参数。

名称 描述 默认值
sqlite_debug_show_queries 调试设置:将发送给 SQLite 的所有查询打印到 stdout false

支持的操作

以下是支持的操作列表。

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;

事务

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
 

已弃用:旧的 sqlite_attach 函数已被弃用。建议切换到新的 ATTACH 语法

© 2025 DuckDB 基金会,阿姆斯特丹,荷兰
行为准则 商标使用指南