⌘+k ctrl+k
1.1.3 (stable)
Search Shortcut cmd + k | ctrl + k
ATTACH and DETACH Statements

DuckDB 允许附加和分离数据库文件。

Examples

附加数据库 file.db 并使用从名称推断的别名 (file):

ATTACH 'file.db';

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

ATTACH 'file.db' AS file_db;

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

ATTACH 'file.db' (READ_ONLY);

附加数据库 file.db,块大小为16KB:

ATTACH 'file.db' (BLOCK_SIZE 16384);

附加一个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;

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

CREATE TABLE file.new_table (i INTEGER);

分离别名为 file 的数据库:

DETACH file;

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

SHOW DATABASES;

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

USE file;

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://duckdb-blobs/databases/stations.duckdb' AS stations_db;
ATTACH 's3://duckdb-blobs/databases/stations.duckdb' AS stations_db (READ_ONLY);

在DuckDB版本1.1.0之前,必须为HTTP和S3端点指定READ_ONLY标志。

Detach

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

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

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

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

分离语法

Options

Name Description Type Default value
access_mode 数据库的访问模式(AUTOMATIC, READ_ONLY, 或 READ_WRITE VARCHAR automatic
type 文件类型(DUCKDBSQLITE),或从输入字符串字面量(MySQL, PostgreSQL)推断得出。 VARCHAR DUCKDB
block_size 新数据库文件的块大小。必须是2的幂且在[16384, 262144]范围内。不能为现有文件设置。 UBIGINT 262144

名称限定

目录对象的完全限定名称包含对象的目录模式名称。例如:

附加数据库 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;

请注意,通常不需要使用完全限定名称。当名称没有完全限定时,系统会使用目录搜索路径来查找要引用的条目。默认的目录搜索路径包括系统目录、临时目录以及最初附加的数据库和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;

事务语义

在多个数据库上运行查询时,系统会为每个数据库打开单独的事务。默认情况下,事务是延迟启动的——当在查询中首次引用某个数据库时,才会为该数据库启动事务。可以通过切换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.

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