Read按主键或指定字段精确查单条,One需QueryTable+Filter支持复杂条件,All默认限1000行且需手动分页,原生SQL用于JOIN或函数等ORM不支持场景。

Read 和 One 都能查单条,但适用场景完全不同:前者靠主键或指定字段精确匹配结构体,后者必须配合 QueryTable + Filter 使用,且不校验主键。
用 Read 查单条:只认结构体字段,不走 SQL WHERE 条件链
Read 的本质是“按主键或显式字段查唯一行”,它不会拼接任意条件,也不支持 AND/OR 组合。
- 如果只传
&user(无第二参数),默认按主键查询:o.Read(&user)→WHERE id = ? - 若指定字段,如
o.Read(&user, "Name"),则生成WHERE name = ?;多个字段如o.Read(&user, "Name", "Age")→WHERE name = ? AND age = ? - 结构体中未参与查询的字段保持零值,不会被数据库填充
- 错误常见于:字段名拼错(比如写成
"name"但结构体 tag 是orm:"column(Name)"),或传了非结构体字段名(如"profile__age")——Read不识别双下划线表达式
用 One 查单条:依赖 QuerySeter 链式条件,更灵活但易漏 Filter
One 必须挂载在 QueryTable 实例后调用,所有过滤逻辑由前面的 Filter、Exclude 等方法决定。
- 必须至少有一个
Filter,否则One会报ErrNoRows或随机取第一行(行为不可靠) - 支持复杂表达式,如
qs.Filter("created__gte", time.Now().AddDate(0,0,-7))、qs.Filter("title__icontains", "beego") - 可选字段投影:
qs.Filter("id", 123).One(&article, "title", "author"),未列出字段在article中为零值 - 注意:如果数据库返回多行,
One只取第一条,不报错也不警告——这容易掩盖数据重复问题
用 All 查多条:默认上限 1000 行,分页必须手动加 Limit/Offset
All 是最常用的批量查询入口,但它有隐式限制和字段控制细节。
- 不加
Limit时,最多返回 1000 行,超出部分被静默截断(不是报错) - 分页推荐用
Limit(n).Offset(m),而不是Limit(n, m)—— 后者在某些 beego 版本中参数顺序解释不一致 - 字段投影同
One:qs.Filter("status", "active").All(&list, "id", "title", "updated") - 接收变量必须是指针切片,如
[]*models.Article或[]models.Article,类型需与QueryTable参数一致;混用会导致QueryRows类型不匹配错误
原生 SQL 查单条/多条:用 QueryRow 和 QueryRows,但别漏 Raw 参数绑定
当 ORM 条件表达式不够用(比如需要 JOIN、子查询、函数计算),就得切原生 SQL。这时关键在参数安全与结果映射。
-
QueryRow要求 SQL 返回**恰好一行一列**(如SELECT COUNT(*))或能完整映射到结构体的字段(字段名/顺序需匹配) -
QueryRows接收切片指针,但结构体字段必须有对应 db 列名 tag,例如Id int `orm:"column(id)"`;否则字段为空 - 参数建议用
SetArgs分离 SQL 和参数,避免手拼?个数错位:o.Raw("SELECT * FROM user WHERE name = ? AND age > ?").SetArgs("tom", 18).QueryRows(&users) - 别用
Exec去查数据——它只返回sql.Result,没有行内容;用错会得到空结果却无报错
实际项目里,Read 适合 ID 或登录名这类强唯一字段的快速查找;One 适合带业务条件的详情页(如 “查状态=审核中且创建时间最近的订单”);而 All + 分页是列表页标配。原生 SQL 不是备选方案,而是必要手段——尤其当涉及跨表聚合或数据库特有函数时,硬套 ORM 表达式反而增加维护成本。











