⌘+k ctrl+k
1.4 (LTS)
搜索快捷键 cmd + k | ctrl + k
ATTACH 和 DETACH 语句

DuckDB 允许附加(Attach)到数据库文件以及从数据库文件分离(Detach)。

示例

附加数据库 file.db,别名由文件名推断得出(即 file

ATTACH 'file.db';

附加数据库 file.db,并使用显式别名(file_db

ATTACH 'file.db' AS file_db;

以只读模式附加数据库 file.db

ATTACH 'file.db' (READ_ONLY);

以 16 kB 的块大小附加数据库 file.db

ATTACH 'file.db' (BLOCK_SIZE 16_384);

以 2048 行的行组大小附加数据库 file.db

ATTACH 'file.db' (ROW_GROUP_SIZE 2048);

附加一个用于读写的 SQLite 数据库(更多信息请参阅 sqlite 扩展

ATTACH 'sqlite_file.db' AS sqlite_db (TYPE sqlite);

如果推断的数据库别名 file 尚不存在,则附加数据库 file.db

ATTACH IF NOT EXISTS 'file.db';

如果显式数据库别名 file_db 尚不存在,则附加数据库 file.db

ATTACH IF NOT EXISTS 'file.db' AS file_db;

将数据库 file2.db 附加为别名 file_db,如果该别名已存在则先分离并替换之

ATTACH OR REPLACE 'file2.db' AS file_db;

在别名为 file 的附加数据库中创建一个表

CREATE TABLE file.new_table (i INTEGER);

分离别名为 file 的数据库

DETACH file;

显示所有已附加数据库的列表

SHOW DATABASES;

将默认数据库更改为 file 数据库

USE file;

ATTACH

ATTACH 语句将一个新的数据库文件添加到目录中,以便对其进行读写。请注意,附加定义不会在会话之间持久保存:当启动新会话时,您必须重新附加到所有数据库。

ATTACH 语法

ATTACH 允许 DuckDB 操作多个数据库文件,并允许在不同数据库文件之间传输数据。

ATTACH 支持 HTTP 和 S3 端点。对于这些端点,默认情况下它会创建一个只读连接。因此,以下两条命令是等效的

ATTACH 'https://blobs.duckdb.org/databases/stations.duckdb' AS stations_db;
ATTACH 'https://blobs.duckdb.org/databases/stations.duckdb' AS stations_db (READ_ONLY);

同样,以下两条连接到 S3 的命令是等效的

ATTACH 's3://blobs-duckdb/databases/stations.duckdb' AS stations_db;
ATTACH 's3://blobs-duckdb/databases/stations.duckdb' AS stations_db (READ_ONLY);

显式存储版本

DuckDB v1.2.0 引入了 STORAGE_VERSION 选项,允许显式指定存储版本。使用此选项,您可以选择加入更新的、前向不兼容的功能

ATTACH 'file.db' (STORAGE_VERSION 'v1.2.0');

此设置指定了能够读取该数据库文件的最低 DuckDB 版本。当使用此选项写入数据库文件时,生成的那些文件无法被低于指定版本的旧版 DuckDB 打开。它们可以被指定版本以及所有更高版本的 DuckDB 读取。

更多详细信息,请参阅 “存储”页面

数据库加密

DuckDB 支持数据库加密。默认情况下,它使用 AES 加密,密钥长度为 256 位,并使用推荐的 GCM 模式。加密涵盖主数据库文件、预写日志(WAL)文件,甚至临时文件。要附加到加密数据库,请使用带有 ENCRYPTION_KEYATTACH 语句。

ATTACH 'encrypted.db' AS enc_db (ENCRYPTION_KEY 'quack_quack');

为了加密数据,DuckDB 可以使用内置的 mbedtls 库,也可以使用来自 httpfs 扩展的 OpenSSL 库。请注意,由于硬件加速,OpenSSL 版本速度快得多,因此请确保加载 httpfs 以获得良好的加密性能

LOAD httpfs;
ATTACH 'encrypted.db' AS enc_db (ENCRYPTION_KEY 'quack_quack'); -- will be faster thanks to httpfs

要将 AES 模式更改为 CBCCTR,请使用 ENCRYPTION_CIPHER 选项

ATTACH 'encrypted.db' AS enc_db (ENCRYPTION_KEY 'quack_quack', ENCRYPTION_CIPHER 'CBC');
ATTACH 'encrypted.db' AS enc_db (ENCRYPTION_KEY 'quack_quack', ENCRYPTION_CIPHER 'CTR');

数据库加密意味着使用 存储版本 1.4.0 或更高版本。

DuckDB 的加密尚未完全符合官方的 NIST 要求。请关注议题 #20162 “Store and verify tag for canary encryption” 以跟踪我们迈向符合 NIST 标准的进展。

选项

ATTACH 语句后的括号内可以提供零个或多个复制选项。参数值可以通过单引号包裹或不包裹传入。参数值可以使用任意表达式。

名称 描述 类型 默认值
ACCESS_MODE 数据库的访问模式(AUTOMATICREAD_ONLYREAD_WRITE)。 VARCHAR automatic
COMPRESS 数据库是否被压缩。仅适用于内存数据库。 VARCHAR false
TYPE 文件类型(DUCKDBSQLITE),或者根据输入字符串字面量推导(MySQL、PostgreSQL)。 VARCHAR DUCKDB
BLOCK_SIZE 新数据库文件的块大小。必须是 2 的幂且在 [16384, 262144] 范围内。现有文件无法设置此项。 UBIGINT 262144
ROW_GROUP_SIZE 新数据库文件的行组大小。 UBIGINT 122880
STORAGE_VERSION 所使用的存储版本。 VARCHAR v1.0.0
ENCRYPTION_KEY 用于加密数据库的加密密钥。 VARCHAR -
ENCRYPTION_CIPHER 用于加密数据库的加密算法(CBCCTRGCM)。 VARCHAR -

DETACH

DETACH 语句允许关闭并分离先前附加的数据库文件,从而释放对该数据库文件持有的任何锁。

请注意,无法分离默认数据库:如果您想这样做,请执行 USE 语句将默认数据库更改为另一个。例如,如果您连接到一个持久数据库,可以通过执行以下命令切换到内存数据库

ATTACH ':memory:' AS memory_db;
USE memory_db;

警告:关闭连接(例如在 Python 中调用 close() 函数)不会释放对数据库文件持有的锁,因为文件句柄由 DuckDB 主实例(在 Python 的情况下为 duckdb 模块)持有。

DETACH 语法

名称限定

目录对象的全限定名称包含对象的目录(catalog)架构(schema)名称(name)。例如

附加数据库 new_db

ATTACH 'new_db.db';

在数据库 new_db 中创建架构 my_schema

CREATE SCHEMA new_db.my_schema;

在架构 my_schema 中创建表 my_table

CREATE TABLE new_db.my_schema.my_table (col INTEGER);

引用表 my_table 中的列 col

SELECT new_db.my_schema.my_table.col FROM new_db.my_schema.my_table;

请注意,通常不需要全限定名称。当名称不是全限定时,系统会使用目录搜索路径(catalog search path)来查找要引用的条目。默认的目录搜索路径包括系统目录、临时目录以及最初附加的数据库,以及 main 架构。

另请注意关于 标识符和数据库名称的具体规则

默认数据库和架构

当创建表而不进行任何限定时,该表将在默认数据库的默认架构中创建。默认数据库是系统启动时加载的数据库,而默认架构是 main

在默认数据库中创建表 my_table

CREATE TABLE my_table (col INTEGER);

更改默认数据库和架构

可以使用 USE 命令更改默认数据库和架构。

将默认数据库架构设置为 new_db.main

USE new_db;

将默认数据库架构设置为 new_db.my_schema

USE new_db.my_schema;

解决冲突

当仅提供单个限定符时,只要没有冲突,系统就可以将其解释为目录架构。例如

ATTACH 'new_db.db';
CREATE SCHEMA my_schema;

创建表 new_db.main.tbl

CREATE TABLE new_db.tbl (i INTEGER);

创建表 default_db.my_schema.tbl

CREATE TABLE my_schema.tbl (i INTEGER);

如果我们创建了一个冲突(即我们同时拥有一个同名的架构和一个同名的目录),系统要求使用全限定路径

CREATE SCHEMA new_db;
CREATE TABLE new_db.tbl (i INTEGER);
Binder Error:
Ambiguous reference to catalog or schema "new_db" - use a fully qualified path like "memory.new_db"

更改目录搜索路径

可以通过设置 search_path 配置选项来调整目录搜索路径,该选项使用逗号分隔的值列表。以下示例演示了在两个数据库中进行搜索

ATTACH ':memory:' AS db1;
ATTACH ':memory:' AS db2;
CREATE table db1.tbl1 (i INTEGER);
CREATE table db2.tbl2 (j INTEGER);

使用全限定名称引用表

SELECT * FROM db1.tbl1;
SELECT * FROM db2.tbl2;

或者设置搜索路径并使用名称引用表

SET search_path = 'db1,db2';
SELECT * FROM tbl1;
SELECT * FROM tbl2;

事务语义

当在多个数据库上运行查询时,系统会为每个数据库打开单独的事务。事务默认是惰性(lazily)启动的——当查询中第一次引用某个特定数据库时,该数据库的事务才会启动。可以通过设置 SET immediate_transaction_mode = true 来更改此行为,改为在所有已附加数据库中立即启动事务。

虽然可以同时激活多个事务,但系统只支持在单个事务中写入单个已附加的数据库。如果您尝试在单个事务中写入多个已附加的数据库,则会抛出以下错误

Attempting to write to database "db2" in a transaction that has already modified database "db1" -
a single transaction can only write to a single attached database.

此限制的原因是系统不维护跨附加数据库的事务原子性。事务仅在每个数据库文件内部是原子的。通过限制全局事务只能写入单个数据库文件,可以保持原子性保证。

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