前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >sqlx库使用

sqlx库使用

原创
作者头像
Johns
修改2022-07-25 22:41:23
1.1K0
修改2022-07-25 22:41:23
举报
文章被收录于专栏:代码工具

介绍

sqlx是基于Go内置database/sql包上的扩展,主要是简化了sql的使用过程, sqlx的sql.DB, sql.TX, sql.Stmt等保持底层实现不变,因此可以很方便地从database/sql切换到sqlx。sqlx另外还提供了一些功能:

  • 可以将Rows内容解析至struct(支持内嵌)、map、slice
  • 命名参数支持
  • Get/Select可以快速将查询结果转为为struct/slice

安装和连接

代码语言:go
复制
go get github.com/jmoiron/sqlx
代码语言:go
复制
import (
	_ "github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
)

func main(){
  //连接数据库
	// 只用 sqlx.Open() 函数创建连接池,此时只是初始化了连接池,并没有连接数据库.
    // 连接都是惰性的,只有调用 sqlx.DB 的方法时,
	// 此时才真正用到了连接,连接池才会去创建连接.
	DB, err := sqlx.Open("mysql", "root:Guogr@12345@tcp(127.0.0.1:3306)/test?charset=utf8")
	if err != nil {
		fmt.Println("connect error:", err)
	}
	defer DB.Close()

	err = DB.Ping()
	if err != nil {
		fmt.Println("connect ping error:", err)
	}

	// 连接池配置
	DB.SetMaxIdleConns(100)
	DB.SetMaxOpenConns(500)
	DB.SetConnMaxIdleTime(5*time.Minute) 
}

表和表实例定义

代码语言:sql
复制
CREATE TABLE `person` (
		`first_name` text,
		`last_name` text,
		`email` text,
		`id` int NOT NULL AUTO_INCREMENT,
		PRIMARY KEY (`id`)
	) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4;

使用struct需要注意,sqlx默认解析的tag为"db",未设置tag,默认情况下是直接将field名转换为小写,因此默认情况下不满足需求时,需要注意设置field的tag名,否则可能导致数据解析失败。

代码语言:go
复制
// Person 用户信息表
type Person struct {
	Id        int
	FirstName string `db:"first_name"`
	LastName  string `db:"last_name"`
	Email     string `db:"email"`
}

插入操作(单条/批量插入)

代码语言:go
复制
	sqlStr := "insert into person(first_name, last_name, email) values (?,?,?)"
	ret, err := DB.Exec(sqlStr, "Jason", "Moron", "jmoiron@jmoiron.net")
	if err != nil {
		fmt.Println("插入出错", err)
		return
	}
	theID, err := ret.LastInsertId() // 新插入数据的id
	if err != nil {
		fmt.Println("获取插入的id错误:", err)
		return
	}
	fmt.Println("插入成功,id为:", theID)

	ret, err = DB.NamedExec("INSERT INTO person (first_name, last_name, email) 		  VALUES (:first_name, :last_name, :email)",
		&Person{FirstName: "Jane", LastName: "Citizen", 
		Email: "jane.citzen@example.com"})
	if err != nil {
		fmt.Println("插入出错", err)
		return
	}
	theID, err = ret.LastInsertId() // 新插入数据的id
	if err != nil {
		fmt.Println("获取插入的id错误:", err)
		return
	}
	fmt.Println("插入成功,id为:", theID)

	// batch insert with structs
	personStructs := []Person{
		{FirstName: "Ardie0", LastName: "Savea", Email: "asavea@ab.co.nz"},
		{FirstName: "Sonny Bill0", LastName: "Williams", Email: "sbw@ab.co.nz"},
		{FirstName: "Ngani0", LastName: "Laumape", Email: "nlaumape@ab.co.nz"},
	}

	ret, err = DB.NamedExec(`INSERT INTO person (first_name, last_name, email)
        VALUES (:first_name, :last_name, :email)`, personStructs)
	if err != nil {
		fmt.Println("批量插入出错", err)
		return
	}

	affectRows, err := ret.RowsAffected()
	fmt.Printf("affect rows:%d, err=%v \n", affectRows, err)

事务操作

代码语言:go
复制
	// batch insert with maps
	personMaps := []map[string]interface{}{
		{"first_name": "Ardie1", "last_name": "Savea", 
		"email": "asavea@ab.co.nz"},
		{"first_name": "Sonny Bill1", "last_name": "Williams", 
		"email": "sbw@ab.co.nz"},
		{"first_name": "Ngani1", "last_name": "Laumape", 
		"email": "nlaumape@ab.co.nz"},
	}
	// 开启事务
	tx, err := DB.Beginx()
	_, err = tx.NamedExec(`INSERT INTO person (first_name, last_name, email)
        VALUES (:first_name, :last_name, :email)`, personMaps)
	if err != nil {
		// 出错就回滚
		tx.Rollback()
		fmt.Println("批量插入出错", err)
		return
	}
	tx.Commit()
	

查询操作(单条/多条记录查询)

代码语言:go
复制
	
	// 2. 查询数据
	sqlStr = "SELECT * FROM person WHERE last_name=:last_name"
	// 使用map做命名查询
	rows, _ := DB.NamedQuery(sqlStr, map[string]interface{}{"last_name": "Savea"})
	defer rows.Close()
	for rows.Next() {
		var m Person
		rows.StructScan(&m)
		fmt.Println(m)
	}
	
	// 使用结构体做命名查询
	var person = Person{LastName: "Savea"}
	rows, _ = DB.NamedQuery(sqlStr, person)
	defer rows.Close()
	for rows.Next() {
		var p Person
		rows.StructScan(&p)
		fmt.Println(p)
	}

Get/Select操作

Get用于查询单条数据,Select则用于查询多条数据,需要注意的是方法中的dest必须满足要求,Get中不能为nil,Select中必须为slice。

代码语言:go
复制
	
	// Get 查询
	var personGet Person
	err = DB.Get(&personGet, "select * from person where id=?", 1)
	if err != nil {
		fmt.Println("查询出错", err)
	}
	fmt.Println(personGet)
	
	// Select 查询
	var persons []Person
	err = DB.Select(&persons, "select * from person where id > ?", 1)
	if err != nil {
		fmt.Println("查询出错", err)
	}
	fmt.Println(persons)

更新数据

代码语言:go
复制
	// 3 修改数据
	sqlStr = "update person set last_name= ? where id = ?"
	ret, err = DB.Exec(sqlStr, "Savea", 1)
	if err != nil {
		fmt.Println("更新失败", err)
		return
	}
	n, err := ret.RowsAffected()
	if err != nil {
		fmt.Println("获取影响的行数失败:", err)
		return
	}
	fmt.Println("更新成功,影响行数为:", n)

删除数据

代码语言:go
复制
	sqlStr = "delete from person where id = ?"
	ret, err = DB.Exec(sqlStr, 1)
	if err != nil {
		fmt.Println("删除出错:", err)
		return
	}
	n, err = ret.RowsAffected() // 操作影响的行数
	if err != nil {
		fmt.Println("获取操作影响的行数出错:", err)
		return
	}
	fmt.Println("删除成功,影响的行数为:", n)

需要注意的问题

  • 使用query、queryRows返回的rows,应该使用rows.next(),扫描完每一行或者调用rows.close(), 否则该链接永远不会被释放。
  • 不能使用占位符修改sql语句的表结构, 例如下面语句不会生效DB.Query("select * from ?", "person")

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 介绍
  • 安装和连接
  • 表和表实例定义
  • 插入操作(单条/批量插入)
  • 事务操作
  • 查询操作(单条/多条记录查询)
  • Get/Select操作
  • 更新数据
  • 删除数据
  • 需要注意的问题
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档