使用 SQLite 数据库

这篇博客介绍了如何在Windows上使用go-sqlite3驱动进行SQLite数据库操作,包括解决cgo包编译问题和实现增删改查的实例。详细步骤包括下载并安装gcc,以及展示基于Person结构的数据库交互代码。
摘要由CSDN通过智能技术生成

使用 SQLite 数据库

尝试在 Windows 上使用 github.com/mattn/go-sqlite3 驱动,程序会给你以下错误

go get github.com/mattn/go-sqlite3
# github.com/mattn/go-sqlite3
exec: "gcc": executable file not found in %PATH%

go-sqlite3 是一个 cgo 包,要使用 go-sqlite3 构建应用程序,您需要使用 gcc 进行编译,但是在你使用构建和安装 go-sqlite3 之后,你以后可以构建你的应用程序而无需依赖 gcc。因此,请按顺序执行下面提到的步骤

  1. 从这里下载 gcc http://tdm-gcc.tdragon.net/download
  2. 安装 gcc
go get -u github.com/mattn/go-sqlite3
go install github.com/mattn/go-sqlite3

SQLite 增删改查实例

下面的例子显示的如何使用 go-sqlite3 进行数据库操作,结合一个 Person 结构实现了数据库的增删改查操作。

增加数据

// 添加一条数据
func addPerson(person Person) (int64, error) {
	result, err := db.Exec(`INSERT INTO person (name,nickname,created_at) VALUES ($1,$2,$3)`, person.Name, person.Nickname, person.CreatedAt.Format(currentTimeStamp))
	checkErr(err)
	id, err := result.LastInsertId()
	checkErr(err)
	return id, nil
}

更新数据

// 更新一条数据(指定ID)
func updatePerson(person Person) error {
	_, err := db.Exec(`UPDATE person SET name = $1,nickname = $2,created_at = $3 WHERE id = $4`, person.Name, person.Nickname, person.CreatedAt, person.ID)
	checkErr(err)
	return nil
}

读取数据

// 读取所有数据
func readAllPerson() ([]Person, error) {
	rows, err := db.Query(`SELECT * FROM person`)
	defer rows.Close()
	checkErr(err)

	var result []Person
	for rows.Next() {
		v := Person{}
		err := rows.Scan(&v.ID, &v.Name, &v.Nickname, TimeStamp{&v.CreatedAt})
		checkErr(err)
		result = append(result, v)
	}
	return result, nil
}

删除数据

// 删除一条数据(指定ID)
func deletePerson(person Person) error {
	_, err := db.Exec(`DELETE FROM person WHERE id = $1`, person.ID)
	checkErr(err)
	return nil
}

完整代码

sqlite.sql 文件

DROP TABLE person;

CREATE TABLE IF NOT EXISTS person (
    id INTEGER PRIMARY KEY AUTOINCREMENT,   --主键
    name TEXT NOT NULL UNIQUE,              --名字
    nickname TEXT NOT NULL ,                --昵称
    created_at INTEGER NOT NULL             --创建时间
);

main.go 文件

package main

import (
	"database/sql"
	"database/sql/driver"
	"errors"
	"fmt"
	_ "github.com/mattn/go-sqlite3"
	"io/ioutil"
	"log"
	"strings"
	"time"
)

/*!
具体请参考 https://pkg.go.dev/github.com/lib/pq

增删查改(英语:CRUD[注 1]),全称增加(Create,意为“创建”)、删除(Delete)、查询(Read,意为“读取”)、改正(Update,意为“更新”)。
在计算机程序语言中是一连串常见的动作行为,而其行为通常是为了针对某个特定资源所作出的举动(例如:创建资料、读取资料等)。

中文	英文		中文	SQL		HTTP
增加	Create	创建	INSERT	PUT / POST
删除	Delete	删除	DELETE	DELETE
查询	Read	读取	SELECT	GET
改正	Update	更新	UPDATE	PUT / POST
*/

var (
	db      *sql.DB // 数据库句柄
	lastErr error
)

const currentTimeStamp = "2006-01-02 15:04:05Z07:00"

type TimeStamp struct {
	*time.Time
}

// Scan 因 sqlite 驱动不支持扫描 time.Time 数据类型,故在此实现一个 Scan 接口以提供该功能.
func (t TimeStamp) Scan(value interface{}) error {
	var err error
	switch v := value.(type) {
	case string:
		*t.Time, err = time.Parse(currentTimeStamp, v)
	case []byte:
		*t.Time, err = time.Parse(currentTimeStamp, string(v))
	default:
		err = errors.New("invalid type for current_timestamp")
	}
	return err
}

func (t TimeStamp) Value() (driver.Value, error) {
	return t.Time.Format(currentTimeStamp), nil
}

// Person 数据库表的结构
type Person struct {
	ID        int64
	Name      string
	Nickname  string
	CreatedAt time.Time
}

// 添加一条数据
func addPerson(person Person) (int64, error) {
	result, err := db.Exec(`INSERT INTO person (name,nickname,created_at) VALUES ($1,$2,$3)`, person.Name, person.Nickname, person.CreatedAt.Format(currentTimeStamp))
	checkErr(err)
	id, err := result.LastInsertId()
	checkErr(err)
	return id, nil
}

// 添加更多数据
func addArrayPerson(person []Person) error {
	tx, err := db.Begin()
	checkErr(err)

	stmt, err := tx.Prepare(`INSERT INTO person (name,nickname,created_at) VALUES ($1,$2,$3)`)
	checkErr(err)
	defer stmt.Close()

	for _, v := range person {
		_, err = stmt.Exec(v.Name, v.Nickname, v.CreatedAt.Format(currentTimeStamp))
		checkErr(err)
	}
	tx.Commit()

	return nil
}

// 更新一条数据(指定ID)
func updatePerson(person Person) error {
	_, err := db.Exec(`UPDATE person SET name = $1,nickname = $2,created_at = $3 WHERE id = $4`, person.Name, person.Nickname, person.CreatedAt, person.ID)
	checkErr(err)
	return nil
}

// 读取所有数据
func readAllPerson() ([]Person, error) {
	rows, err := db.Query(`SELECT * FROM person`)
	defer rows.Close()
	checkErr(err)

	var result []Person
	for rows.Next() {
		v := Person{}
		err := rows.Scan(&v.ID, &v.Name, &v.Nickname, TimeStamp{&v.CreatedAt})
		checkErr(err)
		result = append(result, v)
	}
	return result, nil
}

// 读取指定 name 字段数据
func readPersonByName(person Person) (Person, error) {
	row := db.QueryRow(`SELECT * FROM person WHERE name = $1`, person.Name)

	v := Person{}
	err := row.Scan(&v.ID, &v.Name, &v.Nickname, &v.CreatedAt)
	checkErr(err)
	return v, nil
}

// 删除一条数据(指定ID)
func deletePerson(person Person) error {
	_, err := db.Exec(`DELETE FROM person WHERE id = $1`, person.ID)
	checkErr(err)
	return nil
}

// init 函数是一个包初始化函数,在 main 函数之前自动调用,此函数的主要作用是初始化不能在全局上下文中初始化的全局变量.
func init() {
	db, lastErr = sql.Open("sqlite3", "./person.db")
	checkErr(lastErr)
	//defer db.Close()

	// 测试 [1]
	// 创建表 [1.1]
	lastErr = createSchemaFromSQLFile("sqlite.sql", db)
	checkErr(lastErr)

	// 添加数据 [1.2]
	person := Person{
		Name:      "cheungxiongwei",
		Nickname:  "驭鲸环球",
		CreatedAt: time.Now().UTC(),
	}
	id, _ := addPerson(person)

	// 更新数据 [1.3]
	person.ID = id
	person.Nickname = "cheungxiongwei"
	person.CreatedAt = time.Now().UTC()
	updatePerson(person)

	// 查询数据 [1.4]
	array, _ := readAllPerson()
	for _, person := range array {
		// 打印数据
		log.Println(person.Name, person.Nickname, person.CreatedAt.Format(currentTimeStamp))
	}

	// 删除数据 [1.5]
	deletePerson(person)
}

// 检查&打印错误
func checkErr(err error, args ...string) {
	if err != nil {
		fmt.Println("Error")
		fmt.Println("%q: %s", err, args)
	}
}

// 创建数据表 sql 文件中需要使用 ; 符号隔离语句
func createSchemaFromSQLFile(filename string, db *sql.DB) error {
	fileByte, err := ioutil.ReadFile(filename)
	if err != nil {
		return err
	}

	for _, s := range strings.Split(string(fileByte), ";\n") {
		if s = strings.TrimSpace(s); s == "" {
			continue
		}

		if _, err := db.Exec(s); err != nil {
			return err
		} else {
			log.Printf(s)
		}
	}
	return nil
}

func main() {

}

数据库数据视图

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值