golang SQLite3数据库驱动插件库go-sqlite3的使用

Golang SQLite3 数据库驱动插件库 go-sqlite3 的使用

简介

go-sqlite3 是一个符合内置 database/sql 接口的 SQLite3 驱动程序。

最新稳定版本是 v1.14 或更高版本,不是 v2。

安装

可以使用 go get 命令安装此包:

go get github.com/mattn/go-sqlite3

go-sqlite3 是一个 CGO 包。如果要使用 go-sqlite3 构建应用程序,需要安装 gcc。

重要提示:因为这是一个启用了 CGO 的包,所以需要设置环境变量 CGO_ENABLED=1,并且在路径中要有 gcc 编译器。

基本使用示例

下面是一个完整的 go-sqlite3 使用示例:

package main

import (
	"database/sql"
	"fmt"
	"log"
	
	_ "github.com/mattn/go-sqlite3"
)

func main() {
	// 打开数据库连接
	db, err := sql.Open("sqlite3", "./example.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// 创建表
	sqlStmt := `
	CREATE TABLE IF NOT EXISTS users (
		id INTEGER PRIMARY KEY AUTOINCREMENT,
		name TEXT NOT NULL,
		age INTEGER
	);`
	_, err = db.Exec(sqlStmt)
	if err != nil {
		log.Printf("%q: %s\n", err, sqlStmt)
		return
	}

	// 插入数据
	tx, err := db.Begin()
	if err != nil {
		log.Fatal(err)
	}
	stmt, err := tx.Prepare("INSERT INTO users(name, age) VALUES(?, ?)")
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()
	
	_, err = stmt.Exec("Alice", 25)
	if err != nil {
		log.Fatal(err)
	}
	_, err = stmt.Exec("Bob", 30)
	if err != nil {
		log.Fatal(err)
	}
	tx.Commit()

	// 查询数据
	rows, err := db.Query("SELECT id, name, age FROM users")
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()
	
	for rows.Next() {
		var id int
		var name string
		var age int
		err = rows.Scan(&id, &name, &age)
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(id, name, age)
	}
	err = rows.Err()
	if err != nil {
		log.Fatal(err)
	}
}

连接字符串选项

创建新的 SQLite 数据库或连接到现有数据库时,可以在文件名后附加选项(也称为 DSN 字符串)。

选项附加在 SQLite 数据库文件名后,用 ? 分隔。多个选项可以用 & 连接。

示例:

// 使用共享缓存和内存模式
db, err := sql.Open("sqlite3", "file:test.db?cache=shared&mode=memory")

// 启用外键约束
db, err := sql.Open("sqlite3", "file:test.db?_foreign_keys=1")

// 设置繁忙超时为5000毫秒
db, err := sql.Open("sqlite3", "file:test.db?_busy_timeout=5000")

特性编译

可以通过构建标签启用或禁用 SQLite3 中的特定功能:

# 启用 ICU、JSON1、FTS5 和安全删除功能
go build -tags "icu json1 fts5 secure_delete"

用户认证

go-sqlite3 支持 SQLite 用户认证模块。要使用此功能,需要使用 sqlite_userauth 标签编译包。

创建受保护的数据库:

// 创建用户认证数据库,用户名为admin,密码为admin
db, err := sql.Open("sqlite3", "file:test.s3db?_auth&_auth_user=admin&_auth_pass=admin")

// 使用SHA1密码编码
db, err := sql.Open("sqlite3", "file:test.s3db?_auth&_auth_user=admin&_auth_pass=admin&_auth_crypt=sha1")

内存数据库

使用内存数据库的注意事项:

// 错误的用法 - 每个连接会创建新的内存数据库
db, err := sql.Open("sqlite3", ":memory:")

// 正确的用法 - 使用共享缓存
db, err := sql.Open("sqlite3", "file::memory:?cache=shared")

跨平台编译

在 Linux 上编译

go build -tags "linux"

在 macOS 上编译

# x86
go build -tags "darwin amd64"
# ARM
go build -tags "darwin arm64"

在 Windows 上编译

需要安装 Windows gcc 工具链(如 TDM-GCC)。

常见问题

  1. 数据库被锁定

    db, err := sql.Open("sqlite3", "file:locked.sqlite?cache=shared")
    db.SetMaxOpenConns(1)
    
  2. 内存数据库问题: 使用 "file::memory:?cache=shared" 而不是 ":memory:"

  3. 并发访问: 只读操作可以并发,但写入操作需要同步。

许可证

MIT 许可证:http://mattn.mit-license.org/2018

作者

Yasuhiro Matsumoto (a.k.a mattn)
G.J.R. Timmer


更多关于golang SQLite3数据库驱动插件库go-sqlite3的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang SQLite3数据库驱动插件库go-sqlite3的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Go-SQLite3 使用指南

go-sqlite3 是 Go 语言的一个 SQLite3 数据库驱动,它通过 cgo 封装了 SQLite3 的 C 语言 API。下面我将详细介绍如何使用这个库。

安装

首先需要安装 go-sqlite3:

go get github.com/mattn/go-sqlite3

注意:使用此库需要安装 GCC 编译环境,因为它使用了 cgo。

基本使用

1. 连接数据库

package main

import (
	"database/sql"
	"fmt"
	"log"
	
	_ "github.com/mattn/go-sqlite3"
)

func main() {
	// 打开数据库连接
	db, err := sql.Open("sqlite3", "./test.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()
	
	// 测试连接
	err = db.Ping()
	if err != nil {
		log.Fatal(err)
	}
	
	fmt.Println("成功连接到SQLite数据库")
}

2. 创建表

func createTable(db *sql.DB) {
	sqlStmt := `
	CREATE TABLE IF NOT EXISTS users (
		id INTEGER PRIMARY KEY AUTOINCREMENT,
		name TEXT NOT NULL,
		age INTEGER,
		email TEXT UNIQUE
	);
	`
	_, err := db.Exec(sqlStmt)
	if err != nil {
		log.Printf("%q: %s\n", err, sqlStmt)
		return
	}
	fmt.Println("表创建成功")
}

3. 插入数据

func insertUser(db *sql.DB, name string, age int, email string) {
	stmt, err := db.Prepare("INSERT INTO users(name, age, email) VALUES(?, ?, ?)")
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()

	res, err := stmt.Exec(name, age, email)
	if err != nil {
		log.Fatal(err)
	}

	id, err := res.LastInsertId()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("插入成功,ID: %d\n", id)
}

4. 查询数据

func queryUsers(db *sql.DB) {
	rows, err := db.Query("SELECT id, name, age, email FROM users")
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	for rows.Next() {
		var id int
		var name string
		var age int
		var email string
		err = rows.Scan(&id, &name, &age, &email)
		if err != nil {
			log.Fatal(err)
		}
		fmt.Printf("ID: %d, Name: %s, Age: %d, Email: %s\n", id, name, age, email)
	}

	err = rows.Err()
	if err != nil {
		log.Fatal(err)
	}
}

5. 更新数据

func updateUser(db *sql.DB, id int, newName string) {
	stmt, err := db.Prepare("UPDATE users SET name = ? WHERE id = ?")
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()

	res, err := stmt.Exec(newName, id)
	if err != nil {
		log.Fatal(err)
	}

	affected, err := res.RowsAffected()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("更新了 %d 行\n", affected)
}

6. 删除数据

func deleteUser(db *sql.DB, id int) {
	stmt, err := db.Prepare("DELETE FROM users WHERE id = ?")
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()

	res, err := stmt.Exec(id)
	if err != nil {
		log.Fatal(err)
	}

	affected, err := res.RowsAffected()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("删除了 %d 行\n", affected)
}

高级功能

1. 事务处理

func transactionExample(db *sql.DB) {
	tx, err := db.Begin()
	if err != nil {
		log.Fatal(err)
	}

	// 在事务中执行多个操作
	_, err = tx.Exec("INSERT INTO users(name, age, email) VALUES(?, ?, ?)", "Alice", 25, "alice@example.com")
	if err != nil {
		tx.Rollback()
		log.Fatal(err)
	}

	_, err = tx.Exec("UPDATE users SET age = ? WHERE name = ?", 26, "Bob")
	if err != nil {
		tx.Rollback()
		log.Fatal(err)
	}

	err = tx.Commit()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("事务执行成功")
}

2. 使用连接池

func connectionPoolExample() {
	db, err := sql.Open("sqlite3", "./test.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// 设置连接池参数
	db.SetMaxOpenConns(10) // 最大打开连接数
	db.SetMaxIdleConns(5)  // 最大空闲连接数
	db.SetConnMaxLifetime(time.Hour) // 连接最大存活时间

	// 使用数据库...
}

3. 使用预编译语句

func preparedStatementExample(db *sql.DB) {
	// 准备语句
	stmt, err := db.Prepare("SELECT name FROM users WHERE age > ?")
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()

	// 多次使用同一语句
	rows, err := stmt.Query(20)
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	for rows.Next() {
		var name string
		err = rows.Scan(&name)
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(name)
	}
}

注意事项

  1. 并发访问:SQLite3 是文件数据库,多个写操作需要串行执行。go-sqlite3 内部已经处理了并发问题。

  2. 内存模式:可以使用 :memory: 作为数据库文件名创建内存数据库:

    db, err := sql.Open("sqlite3", ":memory:")
    
  3. 性能优化:对于大量插入操作,考虑使用事务可以显著提高性能。

  4. CGO依赖:由于使用了 cgo,交叉编译时需要特别注意。

  5. 扩展支持:go-sqlite3 支持 SQLite3 的扩展,可以通过 Register 函数注册自定义扩展。

希望这个指南能帮助你开始使用 go-sqlite3。根据你的具体需求,可以进一步探索更高级的功能。

回到顶部