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 |
文件类型(DUCKDB 或 SQLITE),或从输入字符串字面量(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.
这种限制的原因是系统不维护跨附加数据库的事务原子性。事务仅在每个数据库文件内部是原子的。通过限制全局事务只能写入单个数据库文件,可以保持原子性保证。