Go sqlite3
最后修改时间 2024 年 4 月 11 日
在本文中,我们将展示如何在 Golang 中使用 sqlite3 数据库。这些示例执行基本的数据库操作。
SQLite 是一个嵌入式关系数据库引擎。其文档称它是一个独立、无服务器、零配置和事务性的 SQL 数据库引擎。它非常受欢迎,目前全球有数亿份副本在使用。
Go 提供了 sql
包,该包提供了 SQL(或类 SQL)数据库的通用接口。sql 包必须与数据库驱动程序一起使用。
创建 SQLite 数据库
我们可以使用 sqlite3
命令行工具创建数据库和查询数据。
$ sudo apt install sqlite3
我们安装该工具。
$ sqlite3 test.db SQLite version 3.37.2 2022-01-06 13:25:41 Enter ".help" for usage hints. sqlite>
我们向 sqlite3
工具提供一个参数;test.db
是数据库名称。它是在我们磁盘上的一个文件。如果文件存在,它将被打开。如果不存在,它将被创建。
sqlite> .tables sqlite> .exit $ ls test.db
.tables
命令会列出 test.db
数据库中的表。目前没有表。.exit
命令会终止 sqlite3
命令行工具的交互式会话。ls
命令显示当前工作目录的内容。我们可以看到 test.db
文件。所有数据将存储在这个单一文件中。
Go sqlite3 版本
在第一个示例中,我们打印 sqlite3 的版本。
package main import ( "database/sql" "fmt" "log" _ "github.com/mattn/go-sqlite3" ) func main() { db, err := sql.Open("sqlite3", ":memory:") if err != nil { log.Fatal(err) } defer db.Close() var version string err = db.QueryRow("SELECT SQLITE_VERSION()").Scan(&version) if err != nil { log.Fatal(err) } fmt.Println(version) }
该程序返回 sqlite3 的版本。版本是通过执行 SELECT SQLITE_VERSION()
语句确定的。
_ "github.com/mattn/go-sqlite3"
当一个包被导入并带有空白标识符前缀时,该包的 init 函数会被调用。该函数注册驱动程序。
db, err := sql.Open("sqlite3", ":memory:")
使用 sql.Open
,我们可以打开一个由其数据库驱动程序名称和特定于驱动程序的数据源名称指定的数据库。在我们的例子中,我们连接到内存数据库。
defer db.Close()
Close
函数关闭数据库并阻止新的查询开始。
err = db.QueryRow("SELECT SQLITE_VERSION()").Scan(&version)
QueryRow
执行一个预期最多返回一行的查询。Scan
函数将匹配行中的列复制到 version
变量。
$ go run main.go 3.38.5
Go sqlite3 Exec
Exec
函数执行一个不返回任何行的查询。
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() sts := ` DROP TABLE IF EXISTS cars; CREATE TABLE cars(id INTEGER PRIMARY KEY, name TEXT, price INT); INSERT INTO cars(name, price) VALUES('Audi',52642); INSERT INTO cars(name, price) VALUES('Mercedes',57127); INSERT INTO cars(name, price) VALUES('Skoda',9000); INSERT INTO cars(name, price) VALUES('Volvo',29000); INSERT INTO cars(name, price) VALUES('Bentley',350000); INSERT INTO cars(name, price) VALUES('Citroen',21000); INSERT INTO cars(name, price) VALUES('Hummer',41400); INSERT INTO cars(name, price) VALUES('Volkswagen',21600); ` _, err = db.Exec(sts) if err != nil { log.Fatal(err) } fmt.Println("table cars created") }
在示例中,我们创建一个新表。
db, err := sql.Open("sqlite3", "test.db")
我们创建一个新的文件数据库。
sts := ` DROP TABLE IF EXISTS cars; CREATE TABLE cars(id INTEGER PRIMARY KEY, name TEXT, price INT); INSERT INTO cars(name, price) VALUES('Audi',52642); INSERT INTO cars(name, price) VALUES('Mercedes',57127); INSERT INTO cars(name, price) VALUES('Skoda',9000); INSERT INTO cars(name, price) VALUES('Volvo',29000); INSERT INTO cars(name, price) VALUES('Bentley',350000); INSERT INTO cars(name, price) VALUES('Citroen',21000); INSERT INTO cars(name, price) VALUES('Hummer',41400); INSERT INTO cars(name, price) VALUES('Volkswagen',21600); `
这些是创建新表的 SQL 语句。
_, err = db.Exec(sts)
这些语句使用 Exec
执行。
Go sqlite3 使用 Query 选择所有行
Query
执行一个返回行的查询,通常是 SELECT。可选参数是查询中的任何占位符参数。
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() rows, err := db.Query("SELECT * FROM cars") if err != nil { log.Fatal(err) } defer rows.Close() for rows.Next() { var id int var name string var price int err = rows.Scan(&id, &name, &price) if err != nil { log.Fatal(err) } fmt.Printf("%d %s %d\n", id, name, price) } }
该示例从 cars
表中选择所有行。
rows, err := db.Query("SELECT * FROM cars")
这是选择所有行的 SQL。
for rows.Next() {
Next
方法准备好下一行结果供 Scan
方法读取。如果成功则返回 true,如果不存在下一行结果或在准备过程中发生错误则返回 false。
err = rows.Scan(&id, &name, &price)
我们将行读取到变量中。
fmt.Printf("%d %s %d\n", id, name, price)
当前行被打印出来。
$ go run main.go 1 Audi 52642 2 Mercedes 57127 3 Skoda 9000 4 Volvo 29000 5 Bentley 350000 6 Citroen 21000 7 Hummer 41400 8 Volkswagen 21600
Go sqlite3 预编译语句
使用预编译语句,我们使用占位符而不是直接将值写入语句。预编译语句提高了数据库操作的安全性和性能。
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() stm, err := db.Prepare("SELECT * FROM cars WHERE id = ?") if err != nil { log.Fatal(err) } defer stm.Close() var id int var name string var price int cid := 3 err = stm.QueryRow(cid).Scan(&id, &name, &price) if err != nil { log.Fatal(err) } fmt.Printf("%d %s %d\n", id, name, price) }
我们使用预编译语句来选择一个特定行。
stm, err := db.Prepare("SELECT * FROM cars WHERE id = ?")
Prepare
函数创建用于后续查询或执行的预编译语句。占位符 ? 稍后将被值填充。
err = stm.QueryRow(cid).Scan(&id, &name, &price)
传递给 QueryRow
函数的值会映射到占位符。Scan
函数将匹配行中的列复制到变量中。
$ go run main.go 3 Skoda 9000
也可以使用 QueryRow
在一步中完成预编译语句。
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() cid := 3 var id int var name string var price int row := db.QueryRow("SELECT * FROM cars WHERE id = ?", cid) err = row.Scan(&id, &name, &price) if err != nil { log.Fatal(err) } fmt.Printf("%d %s %d\n", id, name, price) }
该示例创建一个预编译语句;这次使用的是 QueryRow
。
Go sqlite3 受影响的行数
RowsAffected
返回受 update、insert 或 delete 语句影响的行数。
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() res, err := db.Exec("DELETE FROM cars WHERE id IN (1, 2, 3)") if err != nil { log.Fatal(err) } n, err := res.RowsAffected() if err != nil { log.Fatal(err) } fmt.Printf("The statement has affected %d rows\n", n) }
在代码示例中,我们使用 DELETE SQL 语句删除了三行。然后我们使用 RowsAffected
打印删除的行数。
$ go run main.go The statement has affected 3 rows
来源
在本文中,我们研究了 Go 中的 sqlite3。