高级查询

1 智能选择字段

在GORM中,你可以针对特定字段使用 Select method。这在处理大型模型但只需要部分字段时尤其有用,尤其是在 API 响应中。

type User struct {
  ID     uint
  Name   string
  Age    int
  Gender string
  // hundreds of fields
}

type APIUser struct {
  ID   uint
  Name string
}

// GORM will automatically select `id`, `name` fields when querying
db.Model(&User{}).Limit(10).Find(&APIUser{})
// SQL: SELECT `id`, `name` FROM `users` LIMIT 10

QueryFields 模式是 GORM 中一个​​解决多表字段冲突​​的高级特性,特别针对复杂 JOIN 查询中的字段歧义问题设计。

2 Locking

clause.Locking是 GORM 中控制数据库锁机制的核心配置,用于实现悲观锁并发控制。

2.1.1 Strength- 锁强度控制

​可选值​

​等效 SQL​

​锁类型​

​适用场景​

"UPDATE"

FOR UPDATE

排他锁 (X锁)

更新前锁定,防止其他事务修改

"SHARE"

LOCK IN SHARE MODE

共享锁 (S锁)

读取时允许共享锁,阻止排他锁

""(空)

无锁

-

默认不添加锁

2.1.2 Options- 锁行为选项

​可选值​

​数据库支持​

​行为描述​

​超时处理​

"NOWAIT"

PostgreSQL, MySQL 8+, Oracle

立即返回错误,不等待锁释放

ErrLockWaitTimeout

"SKIP LOCKED"

PostgreSQL, MySQL 8+, Oracle

跳过被锁定的行

静默跳过

""(空)

所有数据库

默认等待锁释放

可能永久阻塞

2.1.3 Table- 锁目标表

​配置方式​

​说明​

​SQL 示例​

clause.CurrentTable

锁定主表 (默认)

SELECT ... FOR UPDATE

clause.Table{Name: "orders"}

锁定指定表

SELECT ... FOR UPDATE OF orders

clause.Table{Name: "alias"}

锁定表别名

SELECT ... FOR UPDATE OF alias

3 子查询

子查询是 SQL 中一个强大的功能,允许嵌套查询。当使用 *gorm.DB 对象作为参数时,GORM 可以自动生成子查询。

3.1 从子查询中查询

GORM 允许在 FROM 子句中使用子查询,从而实现复杂的查询和数据组织。

4 多列IN

GORM 支持具有多列的 IN 子句,允许在单个查询中根据多个字段值过滤数据。

5 FirstOrInit/Attrs/Assign

这三个方法组合使用可以实现强大的"查找或初始化"模式,特别适合需要灵活处理对象状态的场景。

方法​

​功能​

​执行时机​

​数据库影响​

FirstOrInit

查找记录或初始化对象

立即执行查询

不修改数据库

Attrs

设置初始化属性

仅当记录不存在时应用

不修改数据库

Assign

设置强制属性

无论记录是否存在都应用

不修改数据库

5.1 FirstOrInit(dest interface{}, conds ...interface{}) (tx *DB)

  • 查找匹配的第一条记录,如果不存在则​​初始化​​目标结构体(不保存到数据库)

特点​​:

  • 纯内存操作,不产生 SQL 写操作

  • 初始化对象可用于后续处理(如展示默认表单)

  • 常与 AttrsAssign链式组合

5.2 Attrs(attrs ...interface{}) (tx *DB)

  • 设置​​仅当记录不存在时​​应用的属性

特点​​:

  • 相当于"默认值"提供者

  • 支持结构体和 map 参数

  • 不影响已存在记录的初始化

5.3 Assign(attrs ...interface{}) (tx *DB)

  • 设置​​无论记录是否存在​​都应用的属性

特点​​:

  • 强制覆盖属性值

  • 常用于统计字段更新

  • 支持链式调用多次赋值

5.4 FirstOrCreate

  • 用于获取符合给定条件的第一条记录,如果未找到匹配记录则创建新记录。

  • 可以和 attrs 配合使用,这些属性用于创建记录,但不用于初始搜索查询。

  • 可以和 assign 配合使用, Assign 方法都会设置记录的属性,并将这些属性保存回数据库。

6 优化器/索引提示

GORM 支持优化器和索引提示,允许影响查询优化器的执行计划。这在优化查询性能或处理复杂查询时特别有用。

优化器提示是一些指令,用于指示数据库的查询优化器应如何执行查询。GORM 通过 gorm.io/hints 包方便地使用优化器提示。

提示函数​

​适用数据库​

​功能描述​

​SQL 等效​

UseIndex(hint string)

MySQL

建议使用指定索引

USE INDEX (index_name)

ForceIndex(hint string)

MySQL

强制使用指定索引

FORCE INDEX (index_name)

IgnoreIndex(hint string)

MySQL

忽略指定索引

IGNORE INDEX (index_name)

UseHashJoin()

PostgreSQL

建议使用哈希连接

/*+ HashJoin(t1 t2) */

UseMergeJoin()

PostgreSQL

建议使用合并连接

/*+ MergeJoin(t1 t2) */

UseNestedLoop()

PostgreSQL

建议使用嵌套循环连接

/*+ NestLoop(t1 t2) */

WithIndex(index string)

SQL Server

强制使用索引

WITH (INDEX(index_name))

NoLock()

SQL Server

使用 NOLOCK 提示

WITH (NOLOCK)

StraightJoin()

MySQL

强制按书写顺序连接表

STRAIGHT_JOIN

SetVar(key, value string)

MySQL 8.0+

设置会话变量

SET_VAR(optimizer_switch='condition_fanout_filter=off')

7 批量查询

使用 FindInBatches ,GORM 可以按指定的批次大小处理记录。在批处理函数内部,可以对每一批记录应用操作。

FindInBatches 是一种有效的工具,可以以可管理的块形式处理大量数据,优化资源使用和性能。

8 Pluck

GORM 中的 Pluck 方法用于从数据库中查询单个列,并将结果扫描到切片中。当需要从模型中检索特定字段时,此方法非常理想。

9 Scopes

Scopes 是 GORM 中​​构建模块化、可复用查询条件​​的核心机制,它通过将查询逻辑封装为独立函数,实现优雅的链式组合。

10 获取匹配的记录数

可以使用 Count 来确定查询中满足特定条件的记录数。

最后更新于