ATTACH 语句可用于附加表或字典,可适用于将数据库迁移至另一台服务器的场景。
ATTACH TABLE|DICTIONARY|DATABASE [IF NOT EXISTS] [db.]name
该查询不会在存储上创建数据,而是假设数据已经在适当的位置,只是将指定表、字典或数据库的信息添加到服务器中。执行 ATTACH 查询后,服务器将知道表、字典或数据库的存在。
如果表之前已被分离(DETACH 查询),意味着其结构已知,则可以使用简写形式而不定义结构。
ATTACH TABLE 语句显式注册已存在数据文件的表元数据,主要用于两种场景:
ATTACH 查询的文件,并在启动时运行这些查询。某些系统表除外,这些系统表会在服务器上显式创建。ATTACH TABLE 语句手动重新附加被永久分离的表。ATTACH TABLE [IF NOT EXISTS] [db.]name
-- 1. 创建库 CREATE DATABASE IF NOT EXISTS sample_db ON CLUSTER sample_cluster; -- 2. 创建表 DROP TABLE IF EXISTS sample_db.sample_detach ON CLUSTER sample_cluster; CREATE TABLE sample_db.sample_detach ON CLUSTER sample_cluster ( id Int64 ) ENGINE = MergeTree() ORDER BY id; -- 3. 插入测试数据 INSERT INTO sample_db.sample_detach SELECT number FROM numbers(10); -- 4. 查询表中数据 SELECT * FROM sample_db.sample_detach; -- 5. 分离表 DETACH TABLE sample_db.sample_detach; -- 6. 此时查询报错,该表不存在 SELECT * FROM sample_db.sample_detach; -- 7. 附加表 ATTACH TABLE sample_db.sample_detach; -- 8. 验证附加表,有结果表示附加成功 SELECT * FROM sample_db.sample_detach;
该查询使用提供的结构创建一张新表,并从 user_files 中提供的目录附加表数据。
ATTACH TABLE name FROM 'path/to/data/' (col1 Type1, ...)
参数 | 是否必填 | 说明 |
|---|---|---|
FROM 'path/to/data/' | 是 |
|
(col1 Type1, ...) | 是 | 表结构定义,需与数据文件格式匹配。 |
完整工作流示例如下:
-- 1. 创建库 CREATE DATABASE IF NOT EXISTS sample_db ON CLUSTER sample_cluster; -- 2. 准备测试数据(使用表函数写入文件) DROP TABLE IF EXISTS sample_db.attach_from_path ON CLUSTER sample_cluster; INSERT INTO TABLE FUNCTION file( '/data00/clickhouse/data/user_files/attach_test/data.TSV', 'TSV', 's String, n UInt64' ) VALUES ('x', 100); -- 3. 验证文件是否存在(通过尝试读取文件内容) SELECT * FROM file( '/data00/clickhouse/data/user_files/attach_test/data.TSV', -- 完整文件路径 'TSV', 's String, n Int64' ) LIMIT 1; -- 若能返回结果,说明文件存在且可读 -- 4. 创建表结构并附加现有数据 ATTACH TABLE sample_db.attach_from_path FROM '/data00/clickhouse/data/user_files/attach_test' ( s String, n UInt64 ) ENGINE = File(TSV); -- 5. 即时查询附加数据 SELECT * FROM sample_db.attach_from_path;
输出结果
┌─s────┬──n─┐ │ x │ 100 │ └──────┴───┘
附加一个先前分离的字典。
ATTACH DICTIONARY [IF NOT EXISTS] [db.]name
-- 1. 创建库 CREATE DATABASE IF NOT EXISTS sample_db ON CLUSTER sample_cluster; -- 2. 创建字典 CREATE DICTIONARY IF NOT EXISTS sample_db.sample_dict ON CLUSTER sample_cluster ( `user_id` UInt64, `username` String, `age` UInt8 DEFAULT 0, `gender` UInt8 DEFAULT 0, `last_login` DateTime ) PRIMARY KEY user_id SOURCE(MySQL( host 'mysql_host.example.com' port 3306 user 'dict_reader' password 'secure_password' db 'user_db' table 'users' )) LAYOUT(FLAT()) LIFETIME(MIN 300 MAX 900); -- 3. 分离字典 DETACH DICTIONARY sample_db.sample_dict; -- 4. 验证字典已分离(无结果) SHOW DICTIONARIES LIKE 'sample_db.sample_dict'; -- 5. 附加字典 ATTACH DICTIONARY IF NOT EXISTS sample_db.sample_dict; -- 6. 验证附加字典,如果有结果则表示成功 SHOW DICTIONARIES LIKE 'sample_db.sample_dict';
附加一个先前分离的数据库。
ATTACH DATABASE [IF NOT EXISTS] name [ENGINE=]
-- 1. 创建 Ordinary 引擎数据库 CREATE DATABASE IF NOT EXISTS sample_db ENGINE = Ordinary; -- 2. 分离数据库 DETACH DATABASE sample_db; -- 3. 附加 ATTACH DATABASE sample_db ENGINE = Ordinary;
注意
分离数据库后,如果重新附加数据库,需确保分离前后指定的数据库 engine 类型相同。如果 engine 类型不同,会导致之前创建的库、表无法删除。