
go 通过 mattn/go-sqlite3 驱动支持 sqlite 原生的 attach/detach 语句,可在单个数据库连接中挂载多个数据库文件,直接在 sql 层完成跨库 join,避免手动合并数据。
go 通过 mattn/go-sqlite3 驱动支持 sqlite 原生的 attach/detach 语句,可在单个数据库连接中挂载多个数据库文件,直接在 sql 层完成跨库 join,避免手动合并数据。
SQLite 提供了 ATTACH 和 DETACH 语句,允许将多个数据库文件挂载到同一个数据库连接会话中,并通过别名(如 db1, db2)在 SQL 查询中引用不同数据库中的表。这一能力在 Go 中完全可用——无需额外连接、无需应用层拼接数据,只需借助标准 database/sql 接口执行原生 SQL 即可。
✅ 正确用法示例
package main
import (
"database/sql"
"log"
_ "github.com/mattn/go-sqlite3"
)
func main() {
// 打开主数据库(db1.db)
db, err := sql.Open("sqlite3", "./db1.db")
if err != nil {
log.Fatal(err)
}
defer db.Close()
// ATTACH 第二个数据库(绝对路径更可靠,尤其在跨平台时)
_, err = db.Exec("ATTACH DATABASE '/full/path/to/db2.db' AS db2")
if err != nil {
log.Fatal("ATTACH failed:", err)
}
defer func() {
// 确保清理:DETACH 可选,但推荐显式释放资源
_, _ = db.Exec("DETACH DATABASE db2")
}()
// 直接跨库 JOIN 查询(注意:表名前缀为 'db2.TableName')
rows, err := db.Query(`
SELECT a.id, a.name, b.value
FROM main.SomeTable a
INNER JOIN db2.OtherTable b ON b.ref_id = a.id
`)
if err != nil {
log.Fatal("Query failed:", err)
}
defer rows.Close()
for rows.Next() {
var id int
var name, value string
if err := rows.Scan(&id, &name, &value); err != nil {
log.Fatal("Scan failed:", err)
}
log.Printf("ID: %d, Name: %s, Value: %s", id, name, value)
}
}
⚠️ 关键注意事项
- 路径必须是绝对路径:SQLite 要求 ATTACH 中的数据库路径为绝对路径(相对路径行为不可靠,尤其在 os.Chdir() 或容器环境中)。建议使用 filepath.Abs() 或 filepath.Join() 构造。
- 作用域限制:ATTACH/DETACH 仅对当前数据库连接(*sql.DB)有效,且仅限于该连接的会话生命周期;不同连接之间不共享挂载状态。
- 事务与隔离性:所有挂载数据库参与同一事务(若启用),BEGIN/COMMIT 对所有 attached DB 生效,但需确保各库均支持 WAL 模式以提升并发安全性。
- 命名冲突:AS db2 中的别名不能与已存在数据库名(如 main, temp, db2)重复;main 指默认数据库,temp 为临时库。
- 错误处理不可省略:ATTACH 失败(如文件不存在、权限不足、格式错误)会返回错误,应显式检查,否则后续查询将失败。
? 补充技巧
- 若需动态挂载多个库,可封装为函数:
func AttachDB(db *sql.DB, path, alias string) error { absPath, _ := filepath.Abs(path) _, err := db.Exec("ATTACH DATABASE ? AS ?", absPath, alias) return err } - 使用 PRAGMA database_list; 可查询当前已挂载的所有数据库:
rows, _ := db.Query("PRAGMA database_list;") // 输出 name, file 字段,验证挂载是否成功
总之,合理利用 ATTACH/DETACH 不仅简化了多源数据关联逻辑,还显著提升了查询性能与代码可维护性——这是 SQLite 在嵌入式与轻量级场景中极具价值的特性,在 Go 中完全可用且稳定可靠。











