gorm 教程 一(2)https://developer.aliyun.com/article/1391736
Count
获取模型记录数
db.Where("name = ?", "jinzhu").Or("name = ?", "jinzhu 2").Find(&users).Count(&count) SELECT * from USERS WHERE name = 'jinzhu' OR name = 'jinzhu 2'; (users) SELECT count(*) FROM users WHERE name = 'jinzhu' OR name = 'jinzhu 2'; (count) db.Model(&User{}).Where("name = ?", "jinzhu").Count(&count) SELECT count(*) FROM users WHERE name = 'jinzhu'; (count) db.Table("deleted_users").Count(&count) SELECT count(*) FROM deleted_users;
注意: 在查询链中使用 Count 时,必须放在最后一个位置,因为它会覆盖 SELECT 查询条件。
Group 和 Having
rows, err := db.Table("orders").Select("date(created_at) as date, sum(amount) as total").Group("date(created_at)").Rows() for rows.Next() { ... } rows, err := db.Table("orders").Select("date(created_at) as date, sum(amount) as total").Group("date(created_at)").Having("sum(amount) > ?", 100).Rows() for rows.Next() { ... } type Result struct { Date time.Time Total int64 } db.Table("orders").Select("date(created_at) as date, sum(amount) as total").Group("date(created_at)").Having("sum(amount) > ?", 100).Scan(&results)
Joins
指定关联条件
rows, err := db.Table("users").Select("users.name, emails.email").Joins("left join emails on emails.user_id = users.id").Rows() for rows.Next() { ... } db.Table("users").Select("users.name, emails.email").Joins("left join emails on emails.user_id = users.id").Scan(&results) // 多个关联查询 db.Joins("JOIN emails ON emails.user_id = users.id AND emails.email = ?", "jinzhu@example.org").Joins("JOIN credit_cards ON credit_cards.user_id = users.id").Where("credit_cards.number = ?", "411111111111").Find(&user)
Pluck
使用 Pluck 从模型中查询单个列作为集合。如果想查询多个列,应该使用 Scan 代替。
var ages []int64 db.Find(&users).Pluck("age", &ages) var names []string db.Model(&User{}).Pluck("name", &names) db.Table("deleted_users").Pluck("name", &names) // Requesting more than one column? Do it like this: db.Select("name, age").Find(&users)
Scan
将 Scan 查询结果放入另一个结构体中。
type Result struct { Name string Age int } var result Result db.Table("users").Select("name, age").Where("name = ?", 3).Scan(&result) // Raw SQL db.Raw("SELECT name, age FROM users WHERE name = ?", 3).Scan(&result)
更新
更新所有字段
Save 方法在执行 SQL 更新操作时将包含所有字段,即使这些字段没有被修改。
db.First(&user) user.Name = "jinzhu 2" user.Age = 100 db.Save(&user) UPDATE users SET name='jinzhu 2', age=100, birthday='2016-01-01', updated_at = '2013-11-17 21:34:10' WHERE id=111;
更新已更改的字段
如果你只想更新已经修改了的字段,可以使用 Update,Updates 方法。
// 如果单个属性被更改了,更新它 db.Model(&user).Update("name", "hello") UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111; // 使用组合条件更新单个属性 db.Model(&user).Where("active = ?", true).Update("name", "hello") UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111 AND active=true; // 使用 `map` 更新多个属性,只会更新那些被更改了的字段 db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false}) UPDATE users SET name='hello', age=18, actived=false, updated_at='2013-11-17 21:34:10' WHERE id=111; // 使用 `struct` 更新多个属性,只会更新那些被修改了的和非空的字段 db.Model(&user).Updates(User{Name: "hello", Age: 18}) UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 21:34:10' WHERE id = 111; // 警告: 当使用结构体更新的时候, GORM 只会更新那些非空的字段 // 例如下面的更新,没有东西会被更新,因为像 "", 0, false 是这些字段类型的空值 db.Model(&user).Updates(User{Name: "", Age: 0, Actived: false})
更新选中的字段
如果你在执行更新操作时只想更新或者忽略某些字段,可以使用 Select,Omit方法。
db.Model(&user).Select("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false}) UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111; db.Model(&user).Omit("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false}) UPDATE users SET age=18, actived=false, updated_at='2013-11-17 21:34:10' WHERE id=111;
更新列钩子方法
上面的更新操作更新时会执行模型的 BeforeUpdate 和 AfterUpdate 方法,来更新 UpdatedAt 时间戳,并且保存他的 关联。如果你不想执行这些操作,可以使用 UpdateColumn,UpdateColumns 方法。
// Update single attribute, similar with `Update` db.Model(&user).UpdateColumn("name", "hello") UPDATE users SET name='hello' WHERE id = 111; // Update multiple attributes, similar with `Updates` db.Model(&user).UpdateColumns(User{Name: "hello", Age: 18}) UPDATE users SET name='hello', age=18 WHERE id = 111;
批量更新
批量更新时,钩子函数不会执行
db.Table("users").Where("id IN (?)", []int{10, 11}).Updates(map[string]interface{}{"name": "hello", "age": 18}) UPDATE users SET name='hello', age=18 WHERE id IN (10, 11); // 使用结构体更新将只适用于非零值,或者使用 map[string]interface{} db.Model(User{}).Updates(User{Name: "hello", Age: 18}) UPDATE users SET name='hello', age=18; // 使用 `RowsAffected` 获取更新影响的记录数 db.Model(User{}).Updates(User{Name: "hello", Age: 18}).RowsAffected
带有表达式的 SQL 更新
DB.Model(&product).Update("price", gorm.Expr("price * ? + ?", 2, 100)) UPDATE "products" SET "price" = price * '2' + '100', "updated_at" = '2013-11-17 21:34:10' WHERE "id" = '2'; DB.Model(&product).Updates(map[string]interface{}{"price": gorm.Expr("price * ? + ?", 2, 100)}) UPDATE "products" SET "price" = price * '2' + '100', "updated_at" = '2013-11-17 21:34:10' WHERE "id" = '2'; DB.Model(&product).UpdateColumn("quantity", gorm.Expr("quantity - ?", 1)) UPDATE "products" SET "quantity" = quantity - 1 WHERE "id" = '2'; DB.Model(&product).Where("quantity > 1").UpdateColumn("quantity", gorm.Expr("quantity - ?", 1)) UPDATE "products" SET "quantity" = quantity - 1 WHERE "id" = '2' AND quantity > 1;
在钩子函数中更新值
如果你想使用 BeforeUpdate、BeforeSave钩子函数修改更新的值,可以使用 scope.SetColumn方法,例如:
func (user *User) BeforeSave(scope *gorm.Scope) (err error) { if pw, err := bcrypt.GenerateFromPassword(user.Password, 0); err == nil { scope.SetColumn("EncryptedPassword", pw) } }
额外的更新选项
// 在更新 SQL 语句中添加额外的 SQL 选项 db.Model(&user).Set("gorm:update_option", "OPTION (OPTIMIZE FOR UNKNOWN)").Update("name", "hello") UPDATE users SET name='hello', updated_at = '2013-11-17 21:34:10' WHERE id=111 OPTION (OPTIMIZE FOR UNKNOWN);
删除
删除记录
警告:当删除一条记录的时候,你需要确定这条记录的主键有值,GORM会使用主键来删除这条记录。如果主键字段为空,GORM会删除模型中所有的记录。
// 删除一条存在的记录 db.Delete(&email) DELETE from emails where id=10; // 为删除 SQL 语句添加额外选项 db.Set("gorm:delete_option", "OPTION (OPTIMIZE FOR UNKNOWN)").Delete(&email) DELETE from emails where id=10 OPTION (OPTIMIZE FOR UNKNOWN);
批量删除
删除所有匹配的记录
db.Where("email LIKE ?", "%jinzhu%").Delete(Email{}) DELETE from emails where email LIKE "%jinzhu%"; db.Delete(Email{}, "email LIKE ?", "%jinzhu%") DELETE from emails where email LIKE "%jinzhu%";
软删除
如果模型中有 DeletedAt 字段,它将自动拥有软删除的能力!当执行删除操作时,数据并不会永久的从数据库中删除,而是将 DeletedAt 的值更新为当前时间。
db.Delete(&user) UPDATE users SET deleted_at="2013-10-29 10:23" WHERE id = 111; // 批量删除 db.Where("age = ?", 20).Delete(&User{}) UPDATE users SET deleted_at="2013-10-29 10:23" WHERE age = 20; // 在查询记录时,软删除记录会被忽略 db.Where("age = 20").Find(&user) SELECT * FROM users WHERE age = 20 AND deleted_at IS NULL; // 使用 Unscoped 方法查找软删除记录 db.Unscoped().Where("age = 20").Find(&users) SELECT * FROM users WHERE age = 20;