当前位置: 首页 > news >正文

GF框架直接使用SQL语句查询数据库的指南

在GF框架中,我们既可以使用ORM进行便捷的数据库操作,也可以直接使用原生SQL语句来处理复杂的查询需求。本文将详细介绍如何在GF框架中直接使用SQL语句进行数据库查询。

基本用法

1. 直接执行SQL查询

package mainimport ("context""fmt""github.com/gogf/gf/v2/frame/g"
)// 定义数据模型
type ItemOrderInfo struct {OrderId  string `json:"orderId" orm:"order_id" dc:"订单ID"`ItemName string `json:"itemName" orm:"item_name" dc:"商品名称"`
}func main() {ctx := context.Background()var resultsFromSecondDB []ItemOrderInfoerr := g.DB("mysql").Ctx(ctx).Raw("SELECT * FROM rt_itemorder_info WHERE order_id = ?", "12345",).Scan(&resultsFromSecondDB)if err != nil {panic("查询售后订单失败: " + err.Error())}fmt.Printf("查询结果: %+v\n", resultsFromSecondDB)
}

2. 使用命名参数

// 使用命名参数的方式
func queryWithNamedParams() {ctx := context.Background()var results []ItemOrderInfoerr := g.DB("mysql").Ctx(ctx).Raw("SELECT * FROM rt_itemorder_info WHERE order_id = @orderId AND item_name LIKE @itemName",g.Map{"orderId":  "12345","itemName": "%手机%",},).Scan(&results)if err != nil {g.Log().Error(ctx, "查询失败:", err)return}g.Dump(results)
}

高级用法

3. 多数据库连接配置

首先在配置文件中配置多个数据库连接:

# config.yaml
database:default: "mysql"connections:mysql:link: "mysql:root:123456@tcp(127.0.0.1:3306)/test"debug: truesecondDB:link: "mysql:root:123456@tcp(127.0.0.1:3306)/second_db"debug: true

然后使用指定的数据库连接:

func queryFromDifferentDB() {ctx := context.Background()// 使用默认数据库var defaultResults []ItemOrderInfoerr := g.DB().Ctx(ctx).Raw("SELECT * FROM rt_itemorder_info").Scan(&defaultResults)if err != nil {g.Log().Error(ctx, err)}// 使用指定的第二个数据库var secondDBResults []ItemOrderInfoerr = g.DB("secondDB").Ctx(ctx).Raw("SELECT * FROM rt_itemorder_info WHERE order_id = ?", "12345",).Scan(&secondDBResults)if err != nil {panic("查询售后订单失败: " + err.Error())}
}

4. 复杂查询示例

// 复杂SQL查询
func complexQuery() {ctx := context.Background()type OrderDetail struct {OrderId    string    `json:"orderId" orm:"order_id"`ItemName   string    `json:"itemName" orm:"item_name"`TotalAmount float64   `json:"totalAmount" orm:"total_amount"`CreateTime time.Time `json:"createTime" orm:"create_time"`}var orderDetails []OrderDetailsql := `SELECT o.order_id,o.item_name,o.total_amount,o.create_timeFROM rt_itemorder_info oWHERE o.create_time BETWEEN ? AND ?AND o.total_amount > ?ORDER BY o.create_time DESCLIMIT 100`startTime := "2024-01-01 00:00:00"endTime := "2024-12-31 23:59:59"minAmount := 100.0err := g.DB("mysql").Ctx(ctx).Raw(sql, startTime, endTime, minAmount).Scan(&orderDetails)if err != nil {g.Log().Errorf(ctx, "复杂查询失败: %v", err)return}fmt.Printf("找到 %d 条订单记录\n", len(orderDetails))
}

5. 事务中的原生SQL

// 在事务中使用原生SQL
func transactionWithRawSQL() error {ctx := context.Background()return g.DB("mysql").Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {// 查询订单var orderInfo ItemOrderInfoerr := tx.Raw("SELECT * FROM rt_itemorder_info WHERE order_id = ? FOR UPDATE", "12345").Scan(&orderInfo)if err != nil {return err}// 更新订单状态_, err = tx.Raw("UPDATE rt_itemorder_info SET item_name = ? WHERE order_id = ?","更新后的商品名称","12345",).Exec()if err != nil {return err}// 插入日志_, err = tx.Raw("INSERT INTO order_operation_log (order_id, operation, operate_time) VALUES (?, ?, ?)","12345","修改商品名称",time.Now(),).Exec()return err})
}

错误处理最佳实践

// 更健壮的错误处理
func robustQuery(req *Request) ([]ItemOrderInfo, error) {ctx := context.Background()var results []ItemOrderInfoif req.ProductNameAndCode == "" {return nil, fmt.Errorf("产品名称和编码不能为空")}err := g.DB("mysql").Ctx(ctx).Raw("SELECT order_id, item_name FROM rt_itemorder_info WHERE order_id = ?", req.ProductNameAndCode,).Scan(&results)if err != nil {g.Log().Errorf(ctx, "查询订单失败, 参数: %s, 错误: %v", req.ProductNameAndCode, err)return nil, fmt.Errorf("查询售后订单失败: %w", err)}if len(results) == 0 {g.Log().Warningf(ctx, "未找到订单记录, 参数: %s", req.ProductNameAndCode)return nil, nil}return results, nil
}type Request struct {ProductNameAndCode string `json:"productNameAndCode"`
}

性能优化建议

6. 使用预处理语句

// 预处理语句提高性能
func preparedStatementQuery() {ctx := context.Background()// GF框架的Raw方法默认使用预处理语句,无需额外配置var results []ItemOrderInfoerr := g.DB("mysql").Ctx(ctx).Raw("SELECT * FROM rt_itemorder_info WHERE order_id = ? AND item_name LIKE ?","12345","%手机%",).Scan(&results)if err != nil {g.Log().Error(ctx, err)}
}

7. 分页查询

// 分页查询
func paginationQuery(page, pageSize int) ([]ItemOrderInfo, int, error) {ctx := context.Background()var results []ItemOrderInfooffset := (page - 1) * pageSize// 查询数据err := g.DB("mysql").Ctx(ctx).Raw("SELECT * FROM rt_itemorder_info ORDER BY create_time DESC LIMIT ? OFFSET ?",pageSize, offset,).Scan(&results)if err != nil {return nil, 0, err}// 查询总数var total interr = g.DB("mysql").Ctx(ctx).Raw("SELECT COUNT(*) FROM rt_itemorder_info").Scan(&total)if err != nil {return nil, 0, err}return results, total, nil
}

总结

GF框架提供了灵活的原生SQL支持,通过Raw()方法我们可以:

  1. 直接执行任意SQL语句
  2. 使用参数绑定防止SQL注入
  3. 支持多数据库连接
  4. 在事务中使用原生SQL
  5. 享受GF框架的连接池和错误处理优势

使用原生SQL时需要注意:

  • 始终使用参数绑定来防止SQL注入
  • 合理处理错误,避免直接panic
  • 在复杂业务场景中考虑使用事务
  • 注意SQL语句的性能优化

这种方式特别适合复杂查询、报表生成、数据迁移等ORM难以处理的场景。# GF框架直接使用SQL语句查询数据库的完整指南

在GF框架中,我们既可以使用ORM进行便捷的数据库操作,也可以直接使用原生SQL语句来处理复杂的查询需求。本文将详细介绍如何在GF框架中直接使用SQL语句进行数据库查询。

基本用法

1. 直接执行SQL查询

package mainimport ("context""fmt""github.com/gogf/gf/v2/frame/g"
)// 定义数据模型
type ItemOrderInfo struct {OrderId  string `json:"orderId" orm:"order_id" dc:"订单ID"`ItemName string `json:"itemName" orm:"item_name" dc:"商品名称"`
}func main() {ctx := context.Background()var resultsFromSecondDB []ItemOrderInfoerr := g.DB("mysql").Ctx(ctx).Raw("SELECT * FROM rt_itemorder_info WHERE order_id = ?", "12345",).Scan(&resultsFromSecondDB)if err != nil {panic("查询售后订单失败: " + err.Error())}fmt.Printf("查询结果: %+v\n", resultsFromSecondDB)
}

2. 使用命名参数

// 使用命名参数的方式
func queryWithNamedParams() {ctx := context.Background()var results []ItemOrderInfoerr := g.DB("mysql").Ctx(ctx).Raw("SELECT * FROM rt_itemorder_info WHERE order_id = @orderId AND item_name LIKE @itemName",g.Map{"orderId":  "12345","itemName": "%手机%",},).Scan(&results)if err != nil {g.Log().Error(ctx, "查询失败:", err)return}g.Dump(results)
}

高级用法

3. 多数据库连接配置

首先在配置文件中配置多个数据库连接:

# config.yaml
database:default: "mysql"connections:mysql:link: "mysql:root:123456@tcp(127.0.0.1:3306)/test"debug: truesecondDB:link: "mysql:root:123456@tcp(127.0.0.1:3306)/second_db"debug: true

然后使用指定的数据库连接:

func queryFromDifferentDB() {ctx := context.Background()// 使用默认数据库var defaultResults []ItemOrderInfoerr := g.DB().Ctx(ctx).Raw("SELECT * FROM rt_itemorder_info").Scan(&defaultResults)if err != nil {g.Log().Error(ctx, err)}// 使用指定的第二个数据库var secondDBResults []ItemOrderInfoerr = g.DB("secondDB").Ctx(ctx).Raw("SELECT * FROM rt_itemorder_info WHERE order_id = ?", "12345",).Scan(&secondDBResults)if err != nil {panic("查询售后订单失败: " + err.Error())}
}

4. 复杂查询示例

// 复杂SQL查询
func complexQuery() {ctx := context.Background()type OrderDetail struct {OrderId    string    `json:"orderId" orm:"order_id"`ItemName   string    `json:"itemName" orm:"item_name"`TotalAmount float64   `json:"totalAmount" orm:"total_amount"`CreateTime time.Time `json:"createTime" orm:"create_time"`}var orderDetails []OrderDetailsql := `SELECT o.order_id,o.item_name,o.total_amount,o.create_timeFROM rt_itemorder_info oWHERE o.create_time BETWEEN ? AND ?AND o.total_amount > ?ORDER BY o.create_time DESCLIMIT 100`startTime := "2024-01-01 00:00:00"endTime := "2024-12-31 23:59:59"minAmount := 100.0err := g.DB("mysql").Ctx(ctx).Raw(sql, startTime, endTime, minAmount).Scan(&orderDetails)if err != nil {g.Log().Errorf(ctx, "复杂查询失败: %v", err)return}fmt.Printf("找到 %d 条订单记录\n", len(orderDetails))
}

5. 事务中的原生SQL

// 在事务中使用原生SQL
func transactionWithRawSQL() error {ctx := context.Background()return g.DB("mysql").Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {// 查询订单var orderInfo ItemOrderInfoerr := tx.Raw("SELECT * FROM rt_itemorder_info WHERE order_id = ? FOR UPDATE", "12345").Scan(&orderInfo)if err != nil {return err}// 更新订单状态_, err = tx.Raw("UPDATE rt_itemorder_info SET item_name = ? WHERE order_id = ?","更新后的商品名称","12345",).Exec()if err != nil {return err}// 插入日志_, err = tx.Raw("INSERT INTO order_operation_log (order_id, operation, operate_time) VALUES (?, ?, ?)","12345","修改商品名称",time.Now(),).Exec()return err})
}

错误处理最佳实践

// 更健壮的错误处理
func robustQuery(req *Request) ([]ItemOrderInfo, error) {ctx := context.Background()var results []ItemOrderInfoif req.ProductNameAndCode == "" {return nil, fmt.Errorf("产品名称和编码不能为空")}err := g.DB("mysql").Ctx(ctx).Raw("SELECT order_id, item_name FROM rt_itemorder_info WHERE order_id = ?", req.ProductNameAndCode,).Scan(&results)if err != nil {g.Log().Errorf(ctx, "查询订单失败, 参数: %s, 错误: %v", req.ProductNameAndCode, err)return nil, fmt.Errorf("查询售后订单失败: %w", err)}if len(results) == 0 {g.Log().Warningf(ctx, "未找到订单记录, 参数: %s", req.ProductNameAndCode)return nil, nil}return results, nil
}type Request struct {ProductNameAndCode string `json:"productNameAndCode"`
}

性能优化建议

6. 使用预处理语句

// 预处理语句提高性能
func preparedStatementQuery() {ctx := context.Background()// GF框架的Raw方法默认使用预处理语句,无需额外配置var results []ItemOrderInfoerr := g.DB("mysql").Ctx(ctx).Raw("SELECT * FROM rt_itemorder_info WHERE order_id = ? AND item_name LIKE ?","12345","%手机%",).Scan(&results)if err != nil {g.Log().Error(ctx, err)}
}

7. 分页查询

// 分页查询
func paginationQuery(page, pageSize int) ([]ItemOrderInfo, int, error) {ctx := context.Background()var results []ItemOrderInfooffset := (page - 1) * pageSize// 查询数据err := g.DB("mysql").Ctx(ctx).Raw("SELECT * FROM rt_itemorder_info ORDER BY create_time DESC LIMIT ? OFFSET ?",pageSize, offset,).Scan(&results)if err != nil {return nil, 0, err}// 查询总数var total interr = g.DB("mysql").Ctx(ctx).Raw("SELECT COUNT(*) FROM rt_itemorder_info").Scan(&total)if err != nil {return nil, 0, err}return results, total, nil
}

总结

GF框架提供了灵活的原生SQL支持,通过Raw()方法我们可以:

  1. 直接执行任意SQL语句
  2. 使用参数绑定防止SQL注入
  3. 支持多数据库连接
  4. 在事务中使用原生SQL
  5. 享受GF框架的连接池和错误处理优势

使用原生SQL时需要注意:

  • 始终使用参数绑定来防止SQL注入
  • 合理处理错误,避免直接panic
  • 在复杂业务场景中考虑使用事务
  • 注意SQL语句的性能优化

这种方式特别适合复杂查询、报表生成、数据迁移等ORM难以处理的场景。

http://www.dtcms.com/a/549758.html

相关文章:

  • 美食网站素材怎么在网上卖产品
  • 网站建设综合实训设计报告怎么做单位网站
  • JavaWeb后端-JDBC、MyBatis
  • 网站访问流程改变WordPress界面
  • 聚合API平台如何重构AI开发效率?
  • 设计模式之单例模式:一个类就只有一个实例
  • 分布式数据库选型指南 (深入对比TiDB与OceanBase)
  • 模板方法模式:优雅地封装算法骨架
  • 有哪些做ppt用图片的网站有哪些免费咨询皮肤科医生在线
  • 理解 MySQL 架构:从连接到存储的全景视图
  • 电商网站 服务器易派客网站是谁做的
  • 大型语言模型(LLM)架构大比拼
  • 爱派(AiPy):一个让大语言模型直接操作Python完成任务
  • 【一加手机Bootloader解锁政策更新通知】
  • 什么是政企工作手机,有什么功能作用
  • 太原网站排名优化价格室内装修效果图网站有哪些
  • 深入探讨Python中三种核心数据结构:列表、字典和元组。
  • 建网站的几个公司通辽网站网站建设
  • 编辑 JAR 包内嵌套的 TXT 文件(Vim 操作)
  • 网站手机验证码如何做网站做链接代码
  • 无锡做网站6网站看不到预览图
  • Redis 限流最佳实践:令牌桶与滑动窗口全流程实现
  • *清理磁盘空间
  • 用什么软件做网站原型外贸退税流程及方法
  • 微软网站制作软件常见营销策略都有哪些
  • 全栈开源:一套源码快速构建电竞/体育直播平台(PC+H5+双端APP)
  • 淘宝网站维护用DW做的网站怎么弄成链接
  • 【C++】【常见面试题】最简版带大小和超时限制的LRU缓存实现
  • CSAPP实验2:Bomb
  • [人工智能-大模型-118]:模型层 - RNN状态记忆是如何实现的?是通过带权重的神经元,还是通过张量?