
在 GORM 中,db.Raw() 仅构建并准备 SQL 语句,不会自动执行写操作;必须配合 Exec() 才能真正执行 UPDATE、INSERT 或 DELETE 等非查询语句。
在 gorm 中,`db.raw()` 仅构建并准备 sql 语句,不会自动执行写操作;必须配合 `exec()` 才能真正执行 update、insert 或 delete 等非查询语句。
当你在 Go 应用中使用 GORM 操作 Cloud SQL(或其他兼容数据库)时,若尝试通过 db.Raw() 发起 UPDATE 语句却未生效,根本原因在于:*db.Raw() 返回的是一个 `gorm.DB实例,它本身不触发执行——它只是 SQL 构建阶段的中间对象**。只有调用.Exec()(用于无返回结果的写操作)或.Scan()`(用于查询)等终结方法,才会真正向数据库发送请求。
✅ 正确写法如下:
// 方式一:仅执行,检查错误
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 字段可准确获取影响行数(注意:MySQL 默认启用 FOUND_ROWS,PostgreSQL 原生支持,Cloud SQL for MySQL/PostgreSQL 均兼容);
- 参数化占位符统一使用 ?(GORM 自动适配底层驱动),避免 SQL 注入,也提升预处理性能;
- 切勿混用 Raw() + Error 或 RowsAffected —— 这些字段在未执行时始终为零值或 nil,属于常见误用陷阱。
⚠️ 注意事项:
- db.Raw().Scan() 适用于 SELECT;db.Raw().Exec() 才适用于 UPDATE/DELETE/INSERT;
- 若需事务控制,请确保 Exec() 在 db.Transaction() 内调用;
- Cloud SQL 连接需确认已启用 autocommit=false(GORM 默认行为),否则单条 Exec() 会自动提交;如需手动控制,应显式使用事务。
总结:GORM 的链式 API 设计强调“构建 → 执行”分离。记住口诀:Raw 是画图,Exec 是动工。修正调用方式后,你的 UPDATE 语句即可在 Cloud SQL 中稳定生效。











