最近楼主在转go,学习了不少go的知识,今天分享一下遇到的问题,希望能帮到你们。
plus:我觉得gorm的官网写的真不错:https://gorm.io/zh_CN/docs/update.html
楼主在阅读gorm官方文档的时候,学习到了更新子查询,大概就是要通过查询到的值来更新。但是gorm官网给的样例是两个表之间进行的。我想能不能查询本表的值然后更新本表的某一条记录呢?
首先有一张很简单的sql表,users表,结构大概是这样的:
我想完成一个需求,就是让user表内的id=6的记录中的name改成id=7的name。
一开始楼主的代码:
func updateChild(){
u := &User{
ID: 6,
}
tx := db.Model(u).Update("name", db.Table("users").Select("name").Where("id = ?", 7))
fmt.Println(tx.RowsAffected)
}
很好理解对吧,把gorm的语句翻译成sql语句就是:
update users set name = (select name from users where id = 7) where id = 6
但是我本地goland打印的RowsAffected却是0,表示没有更新成功。
我将sql语句写入本地的navicat测试,发现mysql报了一个错。
You can’t specify target table ‘users’ for update in FROM clause
大概是啥意思呢,不能先select出同一表中的某些值,再update这个表(在同一语句中)。
那我们不可能就不完成这个需求吧?这个时候可以用一个中间的临时表来糊弄一下mysql,表示我是从那个临时表查的。把sql改写成这样。
update users set name = (select name from (select name from users where id = 7)as tmp) where id = 6
试试navicat能不能过吧。
很好,没有任何问题。那现在考虑怎么将sql==>gorm语句。
这里参考gorm的官网,你必须得知道这些知识。截图分享给大家。
首先我们肯定得知道如何更新子查询,毕竟我们就是通过子查询的值来更新的,再然我们要知道怎么 from (临时表)。
这里楼主给出自己的代码,可能不是最简洁的,我将临时表抽出来成为一个sub,然后再进行更新子查询即可。
func updateChild(){
u := &User{
ID: 6,
}
tmp := db.Model(&User{}).Select("name").Where("id = ?",7)
tx := db.Model(u).Update("name", db.Select("name").Table("(?)as u", tmp)).Where("id = ?", 6)
fmt.Println(tx.RowsAffected)
}
更新结果: