吉林省网站建设_网站建设公司_响应式网站_seo优化
2025/12/27 8:31:20 网站建设 项目流程

`gorm.Expr` 相当于在 GORM 里开一个“原生 SQL 小窗口”,用来写任意(带占位符的)SQL 表达式,让数据库自己去计算,而不是先查出来再在 Go 代码里算完再写回去。典型用途分三类:

1. 原子更新(避免并发读-改-写)

```go
// 库存 -1
db.Model(&Product{}).
Where("id = ? AND stock > 0", pid).
Update("stock", gorm.Expr("stock - ?", 1))

// 乐观锁版本号 +1
db.Model(&User{ID: 1}).Update("lock_version", gorm.Expr("lock_version + 1"))
```

2. 把表达式当“值”用在 Upsert / Returning 里

```go
// upsert 时只在价格真正变化才更新,并返回被影响的行
db.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "sku"}},
DoUpdates: clause.Assignments(map[string]interface{}{
"price": gorm.Expr("GREATEST(price, VALUES(price))"),
}),
}, clause.Returning{}).Create(&products)
```

3. 复杂 WHERE / ORDER 子句

```go
// 按 FIELD 顺序排序
db.Clauses(clause.OrderBy{
Expression: clause.Expr{
SQL: "FIELD(id, ?)",
Vars: []interface{}{[]int{3, 1, 2}},
WithoutParentheses: true,
},
}).Find(&users)

// jsonb 嵌套字段更新
db.Model(&Quiz{}).Where("id = ?", 1).
Update("answers", gorm.Expr(`jsonb_set(answers, '{multi,"lOjNn9qfJgEGLBIxxe0ka"}', '["B","D"]'::jsonb, true)`))
```

要点小结
- 任何带 `?` 占位符的片段都能传参,防止 SQL 注入 。
- 更新零值、表达式、函数调用时优先用 `gorm.Expr`,否则结构体/Map 会忽略零值 。
- 可嵌进 `clause.Expr{SQL: "...", Vars: ...}` 里,与 GORM 的 Clause 体系无缝衔接 。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询