go sqlx mysql_Go语言增强版操作MySQL(SQLX)

本文介绍了Go语言的sqlx库如何简化MySQL数据库的增删改查操作。通过对比原生方式,展示了sqlx在查询上的便利性,如查询单条和多条记录时可以直接绑定结构体。此外,还提供了添加、更新、删除和事务处理的示例代码,强调sqlx在查询场景中的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

6450318578b3a493c9ed6d7b48e27dc4.png

前言

上次咱们学习了如何使用Go操作Mysql,并且实现了简单的增删改查。

但是相对来说,还有有点复杂的,可能那些大佬也都觉得繁琐叭。

就又开发出了增强版查询Mysql操作库Sqlx。

mod文件

go.mod

module sqlxDemo

go 1.14

require (

github.com/go-sql-driver/mysql v1.4.0

github.com/jmoiron/sqlx v1.2.0

google.golang.org/appengine v1.6.7 // indirect

)

创建数据表

创建表代码

CREATETABLE`userinfo` (

`id` int(11)NOTNULLAUTO_INCREMENT,

`name`varchar(10)DEFAULTNULL,

`phone` char(11)DEFAULTNULL,

`address` varchar(64)DEFAULTNULL,

PRIMARYKEY(`id`)

) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULTCHARSET=utf8mb4;

创建结构体

结构体代码

type Userinfo struct {

Id      int64  `json:"id"`

Namestring `json:"name"`

Phone   string `json:"phone"`

Address string `json:"address"`

}

连接数据库

代码

import (

"fmt"

_ "github.com/go-sql-driver/mysql"

"github.com/jmoiron/sqlx"

)

type Userinfo struct {

Id      int64  `json:"id"`

Namestring `json:"name"`

Phone   string `json:"phone"`

Address string `json:"address"`

}

func main() {

dsn := "root:rootroot@tcp(127.0.0.1:3306)/go_mysql_demo?charset=utf8mb4&parseTime=True"

// 使用 MustConnect 连接的话,验证失败不成功直接panic

//db := sqlx.MustConnect("mysql", dsn)

//使用 Connect连接,会验证是否连接成功,

db, err := sqlx.Connect("mysql", dsn)

if err != nil {

fmt.Printf("connect DB failed, err:%v\n", err)

return

}

db.SetMaxOpenConns(20)

db.SetMaxIdleConns(10)

}

查询单条

我记得使用原来的方式进行查询并且绑定结构体,是这审的。

//查询单条

sqlStr := "SELECT id,`name`,phone,address from userinfo where id = ?;"

var userUserinfo

err = db.QueryRow(sqlStr, 1).Scan(&user.Id, &user.Name, &user.Phone, &user.Address)

if err != nil {

fmt.Println("查询失败", err)

return

}

看第4行代码,需要将结构体的字段一个一个点上去。

如果使用sqlx呢?

代码

//查询

sqlStr := "SELECT id,`name`,phone,address from userinfo where id = ?;"

var userUserinfo

err = db.Get(&user, sqlStr, 1)

if err != nil {

fmt.Println("查询失败:", err)

return

}

fmt.Println("user:",user)

执行结果

46659762ebc01d55a2e2c95bc4cc7cf7.png

还是第4行代码,直接一个结构体扔过去,就绑定成功了。

如果表有很多字段,结构体字段也有很多,这个是很有用的。

查询多条

还是惯例,看看原来是怎么查的。

//查询多条

sqlStr := "SELECT id,`name`,phone,address from userinfo where id >= ?"

//参数同 QueryRow

rows, err := db.Query(sqlStr, 1)

//处理err

// 此处使用rows释放所有链接

defer rows.Close()

//循环整理所有数据

var userList = make([]Userinfo, 0, 10)

forrows.Next() {

var userUserinfo

err = rows.Scan(&user.Id, &user.Name, &user.Phone, &user.Address)

//处理err

userList = append(userList, user)

}

fmt.Println(userList)

为了方便,我去掉了err,使用伪代码处理err代替。

原来的方法,查询出来还得需要一个循环,还需要一个切片,乖乖嘞,打扰了。

来看看sqlx

代码

//查询多条

sqlStr := "SELECT id,`name`,phone,address from userinfo where id >= ?"

var userList []Userinfo

err = db.Select(&userList, sqlStr, 1)

if err != nil {

fmt.Println("查询失败:", err)

return

}

fmt.Println("userList:",userList)

执行结果

5d988229115dfbcce415c7bb975aeca6.png

还是直接扔过去,就绑定完成了,真是美滋滋。

添加

额,添加,更新,删除,事物的话,似乎跟原来差不多,直接看代码叭。

代码

//添加

sqlStr := "INSERT into userinfo(name,phone,address) values(?,?,?);"

result, err := db.Exec(sqlStr,"吴彦祖", 555,"不知道哪的")

if err != nil {

fmt.Println("插入失败", err)

return

}

row_affect, err := result.RowsAffected()

if err != nil {

fmt.Println("受影响行数获取失败:", err)

return

}

fmt.Println("受影响的行数:", row_affect)

lastId, err := result.LastInsertId()

if err != nil {

fmt.Println("新增行id获取失败:", err)

return

}

fmt.Println("新增行id:", lastId)

fmt.Println("插入成功")

执行结果

a5bc6df7f081bacb6acb4f748b7d59c4.png

Mysql

0392ad861a5c7369e40f48444b5ff7f7.png

更新

代码

//更新数据

sqlStr := `UPDATEuserinfosetname=?whereid=?;`

result, err := db.Exec(sqlStr,"吴彦祖666", 4)

if err != nil {

fmt.Println("更新失败", err)

return

}

//受影响的行数

row_affect, err := result.RowsAffected()

if err != nil {

fmt.Println("受影响行数获取失败:", err)

return

}

fmt.Println("受影响的行数:", row_affect)

fmt.Println("更新成功")

执行结果

82dd5923198ae937ed6b6b0ae98a7dfb.png

Mysql

0d77a1cc87bd36baa4bfd4621c6a7038.png

删除

代码

sqlStr :="delete from userinfo where id = ?;"

result, err := db.Exec(sqlStr, 4)

if err != nil {

fmt.Println("删除失败", err)

return

}

//受影响的行数

row_affect, err := result.RowsAffected()

if err != nil {

fmt.Println("受影响行数获取失败:", err)

return

}

fmt.Println("受影响的行数:", row_affect)

fmt.Println("删除成功")

执行结果

09856eebb44dd62f1890ff6eb24ff2bd.png

Mysql

632d1217c8bb80b117e66363d6058742.png

事物

代码

//事物

tx, err := db.Begin()

if err != nil {

//释放事物

if tx != nil {

tx.Rollback()

}

fmt.Println("事物开启失败")

return

}

张三减10块Sql := `UPDATEbillsetmoney=money - 10wherename= ?;`

result, err := tx.Exec(张三减10块Sql,"张三")

if err != nil {

//有错误表示更是失败,回滚原来状态

tx.Rollback()

fmt.Println(err)

return

}

张三受影响行数, err := result.RowsAffected()

if err != nil {

tx.Rollback() // 回滚

return

}

李四加10块Sql := `UPDATEbillsetmoney=money + 10wherename= ?;`

result, err = tx.Exec(李四加10块Sql,"李四")

if err != nil {

//有错误表示更是失败,回滚原来状态

tx.Rollback()

fmt.Println(err)

return

}

李四受影响行数, err := result.RowsAffected()

if err != nil {

tx.Rollback() // 回滚

return

}

//都等于1表示成功,可以提交事务,修改数据

if 张三受影响行数==1 && 李四受影响行数==1{

//提交事务

fmt.Println("提交事务")

tx.Commit()

}else{

//有一个!=1表示没有更新成功,可能用户不存在

fmt.Println("失败了,事物回滚了")

tx.Rollback()

}

fmt.Println("事物执行成功")

执行结果

0b7f68a43a563334240669b53b680c97.png

Mysql

f7f228506ae26a780425ff88a477b726.png

NameExec

做增 删 改使用。

NameExec方法是通过结构体或Map绑定SQL语句,试了试,感觉用处不大,不做举例。

NameQuery

做查询使用。

用法同上,没用,不做举例。

总结

其实sqlx模块,最大的改进是在查询方面,相信你也看到了,确实会比原生查询方便很多很多。

但是在其他方便,就显得捉襟见肘了,但是又说,一般还是查询场景多,查多改少。

afd2f7187f05a5fed70fc883eaa185e6.png

【编辑推荐】

【责任编辑:姜华 TEL:(010)68476606】

点赞 0

<think>嗯,用户问的是SQLx中query_as的用法示例。首先,我需要回忆一下SQLx这个Rust库的相关知识。SQLx是一个异步的Rust SQL库,支持多种数据库,比如PostgreSQL、MySQL等。query_as是其中一个函数,用于将查询结果映射到自定义的结构体上,也就是通常所说的ORM映射。 用户可能已经了解过基本的SQL查询,现在想进一步学习如何将结果转换为结构体。我需要先确认query_as的基本用法,并提供一个简单的例子。可能需要先引入相关的依赖,比如sqlx和对应的数据库驱动,比如PostgreSQL。 然后,结构体需要加上derive宏,比如sqlx::FromRow,这样查询的结果才能自动映射到结构体上。接下来,示例代码应该包括建立数据库连接、执行查询,并使用query_as来获取结果。可能还需要处理错误,但为了示例简洁,可以用问号操作符简化。 另外,用户可能需要知道如何编写SQL语句中的字段别名,如果数据库列名和结构体字段名不一致的话。比如,使用AS关键字来重命名列名,使其与结构体字段匹配。这也是一个常见的注意点,应该在示例中提到。 可能还需要提到异步执行的问题,比如使用tokio或async-std运行时,确保main函数是异步的。在示例中,使用#[tokio::main]来标注main函数,这样可以在异步环境中运行。 用户可能对参数化查询感兴趣,所以可以展示如何在query_as中使用参数,比如查询特定ID的记录。这样示例会更全面,帮助用户理解如何动态构建查询。 最后,需要检查示例代码的正确性,确保结构体字段类型和数据库列类型匹配,比如i32对应INTEGER,String对应TEXT等。如果有时间的话,可以简要说明错误处理,或者引导用户查阅官方文档以获取更多信息。</think>在 Rust 的 sqlx 库中,`query_as` 是一个用于将查询结果自动映射到 Rust 结构体的方法。以下是基础用法示例(使用 PostgreSQL 示例): ```rust use sqlx::{FromRow, PgPool}; // 定义结构体并实现 FromRow trait #[derive(Debug, FromRow)] struct User { id: i32, username: String, email: String, } async fn get_users(pool: &PgPool) -> Result<Vec<User>, sqlx::Error> { // 使用 query_as 直接映射结果 let users = sqlx::query_as::<_, User>( "SELECT id, username, email FROM users WHERE age > $1" ) .bind(18) // 绑定参数 .fetch_all(pool) .await?; Ok(users) } ``` 关键点说明: 1. `#[derive(FromRow)]` 宏自动实现从数据库行到结构体的转换 2. 结构体字段名需与数据库列名一致,或用 `AS` 别名匹配: ```sql SELECT user_id AS id, user_name AS username FROM users ``` 3. 参数绑定使用 `.bind()` 方法,防止 SQL 注入 4. 执行方式: - `.fetch_one()` 获取单条记录 - `.fetch_all()` 获取所有记录 - `.fetch()` 流式获取 带条件查询的完整示例: ```rust #[tokio::main] async fn main() -> Result<(), sqlx::Error> { let pool = PgPool::connect("postgres://user:pass@localhost/db").await?; let user = sqlx::query_as::<_, User>( "SELECT * FROM users WHERE id = $1" ) .bind(42) .fetch_one(&pool) .await?; println!("Found user: {:?}", user); Ok(()) } ``` 注意: 1. 需要开启 sqlx 的相应数据库特性,如 `postgres` 特性 2. 结构体字段类型需与数据库类型兼容 3. 推荐使用 `cargo sqlx prepare` 进行离线查询验证 官方文档建议:<https://docs.rs/sqlx/latest/sqlx/macro.query_as.html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值