
在 GORM 中,db.Raw() 仅构建原始 SQL 查询但不执行它;若需执行更新、插入等写操作,必须调用 db.Exec() 触发实际执行,并检查返回的 sql.Result 获取影响行数或错误。
在 gorm 中,`db.raw()` 仅构建原始 sql 查询但不执行它;若需执行更新、插入等写操作,必须调用 `db.exec()` 触发实际执行,并检查返回的 `sql.result` 获取影响行数或错误。
GORM 的 db.Raw() 方法本质是查询构造器(Query Builder),它返回一个 *gorm.DB 实例,用于链式配置(如参数绑定、上下文设置),但不会自动执行 SQL。这与 db.Exec() 或 db.Find() 等终端方法有根本区别:后者才会真正发送请求到数据库。
因此,您当前的代码:
err := h.db.Raw("update chores set life_status ='Processing' where life_status = 'Active' and chore_type ='Shared' and money_assigned > ? ", 0).Error
实际上等价于:
h.db.Raw("...").Error // → 调用的是 *gorm.DB.Error,而非执行语句后的 error
此时 Raw() 返回的 *gorm.DB 对象尚未执行,.Error 只会返回该 DB 实例自身的初始化错误(如连接未就绪),而非 SQL 执行结果——故始终“看似成功”,实则零行更新。
✅ 正确做法是使用 db.Exec():
result := h.db.Exec(
"UPDATE chores SET life_status = ? WHERE life_status = ? AND chore_type = ? AND money_assigned > ?",
"Processing", "Active", "Shared", 0,
)
if result.Error != nil {
log.Printf("Update failed: %v", result.Error)
return result.Error
}
rowsAffected := result.RowsAffected
log.Printf("Updated %d rows", rowsAffected) // ✅ 真实影响行数
⚠️ 注意事项:
- Exec() 返回 *gorm.Result,其 RowsAffected 字段才是标准 SQL ROW_COUNT() 的映射(MySQL/PostgreSQL 均支持);
- 参数应使用 ? 占位符(SQLite/MySQL)或 $1, $2(PostgreSQL),GORM 会自动适配驱动;
- Cloud SQL(MySQL/PostgreSQL)无特殊限制,但需确保连接池权限允许 UPDATE,且事务未被意外回滚;
- 若需事务控制,请显式使用 h.db.Transaction() 包裹 Exec()。
? 小技巧:为提升可维护性,推荐优先使用 GORM 的结构化更新(避免裸 SQL):
h.db.Model(&Chore{}).
Where("life_status = ? AND chore_type = ? AND money_assigned > ?", "Active", "Shared", 0).
Update("life_status", "Processing")
该方式自动处理参数绑定、类型安全与驱动兼容性,且同样返回 RowsAffected —— 更符合 GORM 的惯用范式。
总结:db.Raw() ≠ 执行,db.Exec() 才是执行原始 SQL 写操作的正确入口;忽略此差异是导致“SQL 无效果”的最常见原因。











