Gosqlite3教程展示了如何在Golang中使用sqlite3数据库。这些示例执行基本的数据库操作。
$ go version go version go1.18.1 linux/amd64
我们使用Go版本1.18。
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文件。所有数据都将存储在这个文件中。
去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的版本。通过执行SELECTSQLITE_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
执行sqlite3
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执行。
Gosqlite3使用查询选择所有行
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
Gosqlite3准备语句
对于准备好的语句,我们使用占位符而不是直接将值写入语句。准备好的语句提高了数据库操作的安全性和性能。
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。
Gosqlite3受影响的行
RowsAffected返回受更新、插入或删除语句影响的行数。
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)
}
在代码示例中,我们使用DELETESQL语句删除了三行。然后我们使用RowsAffected打印删除的行数。
$ go run main.go The statement has affected 3 rows
在本教程中,我们在Go中使用了sqlite3。
列出所有Go教程。
