+
+ CRUD: Reading and Writing Data
+
+
+
+Create
+Create Record
+user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()}
+
+db.NewRecord(user)
+
+db.Create(&user)
+
+db.NewRecord(user)
+
+
+user := User{
+ Name: "jinzhu",
+ BillingAddress: Address{Address1: "Billing Address - Address 1"},
+ ShippingAddress: Address{Address1: "Shipping Address - Address 1"},
+ Emails: []Email{{Email: "jinzhu@example.com"}, {Email: "jinzhu-2@example@example.com"}},
+ Languages: []Language{{Name: "ZH"}, {Name: "EN"}},
+}
+
+db.Create(&user)
+
+
+
+
+
+
+
+
+
+
+
+
+Create With Associations
+Refer Associations for more details
+Default Values
+You could defined default value in the sql
tag, then the generated creating SQL will ignore these fields that including default value and its value is blank, and after inserted the record into databae, gorm will load those fields's value from database.
+type Animal struct {
+ ID int64
+ Name string `sql:"default:'galeone'"`
+ Age int64
+}
+
+var animal = Animal{Age: 99, Name: ""}
+db.Create(&animal)
+
+
+
+
+Setting Primary Key In Callbacks
+If you want to set primary key in BeforeCreate
callback, you could use scope.SetColumn
, for example:
+func (user *User) BeforeCreate(scope *gorm.Scope) error {
+ scope.SetColumn("ID", uuid.New())
+ return nil
+}
+
+
+
+db.Set("gorm:insert_option", "ON CONFLICT").Create(&product)
+
+
+Query
+
+db.First(&user)
+
+
+
+db.Last(&user)
+
+
+
+db.Find(&users)
+
+
+
+db.First(&user, 10)
+
+
+Query With Where (Plain SQL)
+
+db.Where("name = ?", "jinzhu").First(&user)
+
+
+
+db.Where("name = ?", "jinzhu").Find(&users)
+
+
+db.Where("name <> ?", "jinzhu").Find(&users)
+
+
+db.Where("name in (?)", []string{"jinzhu", "jinzhu 2"}).Find(&users)
+
+
+db.Where("name LIKE ?", "%jin%").Find(&users)
+
+
+db.Where("name = ? and age >= ?", "jinzhu", "22").Find(&users)
+
+
+db.Where("updated_at > ?", lastWeek).Find(&users)
+
+db.Where("created_at BETWEEN ? AND ?", lastWeek, today).Find(&users)
+
+Query With Where (Struct & Map)
+
+db.Where(&User{Name: "jinzhu", Age: 20}).First(&user)
+
+
+
+db.Where(map[string]interface{}{"name": "jinzhu", "age": 20}).Find(&users)
+
+
+
+db.Where([]int64{20, 21, 22}).Find(&users)
+
+
+Query With Not
+db.Not("name", "jinzhu").First(&user)
+
+
+
+db.Not("name", []string{"jinzhu", "jinzhu 2"}).Find(&users)
+
+
+
+db.Not([]int64{1,2,3}).First(&user)
+
+
+db.Not([]int64{}).First(&user)
+
+
+
+db.Not("name = ?", "jinzhu").First(&user)
+
+
+
+db.Not(User{Name: "jinzhu"}).First(&user)
+
+
+Query With Inline Condition
+
+db.First(&user, 23)
+
+
+
+db.Find(&user, "name = ?", "jinzhu")
+
+
+db.Find(&users, "name <> ? AND age > ?", "jinzhu", 20)
+
+
+
+db.Find(&users, User{Age: 20})
+
+
+
+db.Find(&users, map[string]interface{}{"age": 20})
+
+
+Query With Or
+db.Where("role = ?", "admin").Or("role = ?", "super_admin").Find(&users)
+
+
+
+db.Where("name = 'jinzhu'").Or(User{Name: "jinzhu 2"}).Find(&users)
+
+
+
+db.Where("name = 'jinzhu'").Or(map[string]interface{}{"name": "jinzhu 2"}).Find(&users)
+
+Query Chains
+Gorm has a chainable API, you could use it like this
+db.Where("name <> ?","jinzhu").Where("age >= ? and role <> ?",20,"admin").Find(&users)
+
+
+db.Where("role = ?", "admin").Or("role = ?", "super_admin").Not("name = ?", "jinzhu").Find(&users)
+
+
+
+db.Set("gorm:query_option", "FOR UPDATE").First(&user, 10)
+
+
+FirstOrInit
+Get the first matched record, or initialize a record with search conditions.
+
+db.FirstOrInit(&user, User{Name: "non_existing"})
+
+
+
+db.Where(User{Name: "Jinzhu"}).FirstOrInit(&user)
+
+db.FirstOrInit(&user, map[string]interface{}{"name": "jinzhu"})
+
+
+Attrs
+Ignore some values when searching, but use them to initialize the struct if record is not found.
+
+db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrInit(&user)
+
+
+
+db.Where(User{Name: "noexisting_user"}).Attrs("age", 20).FirstOrInit(&user)
+
+
+
+
+db.Where(User{Name: "Jinzhu"}).Attrs(User{Age: 30}).FirstOrInit(&user)
+
+
+
+Assign
+Ignore some values when searching, but assign it to the result regardless it is found or not.
+
+db.Where(User{Name: "non_existing"}).Assign(User{Age: 20}).FirstOrInit(&user)
+
+
+
+db.Where(User{Name: "Jinzhu"}).Assign(User{Age: 30}).FirstOrInit(&user)
+
+
+
+FirstOrCreate
+Get the first matched record, or create with search conditions.
+
+db.FirstOrCreate(&user, User{Name: "non_existing"})
+
+
+
+
+db.Where(User{Name: "Jinzhu"}).FirstOrCreate(&user)
+
+
+Attrs
+Ignore some values when searching, but use them to create the struct if record is not found. like FirstOrInit
+
+db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrCreate(&user)
+
+
+
+
+
+db.Where(User{Name: "jinzhu"}).Attrs(User{Age: 30}).FirstOrCreate(&user)
+
+
+
+Assign
+Ignore some values when searching, but assign it to the record regardless it is found or not, then save back to database. like FirstOrInit
+
+db.Where(User{Name: "non_existing"}).Assign(User{Age: 20}).FirstOrCreate(&user)
+
+
+
+
+
+db.Where(User{Name: "jinzhu"}).Assign(User{Age: 30}).FirstOrCreate(&user)
+
+
+
+
+Select
+db.Select("name, age").Find(&users)
+
+
+db.Select([]string{"name", "age"}).Find(&users)
+
+
+db.Table("users").Select("COALESCE(age,?)", 42).Rows()
+
+
+Order
+db.Order("age desc, name").Find(&users)
+
+
+
+db.Order("age desc").Order("name").Find(&users)
+
+
+
+db.Order("age desc").Find(&users1).Order("age", true).Find(&users2)
+
+
+
+Limit
+db.Limit(3).Find(&users)
+
+
+
+db.Limit(10).Find(&users1).Limit(-1).Find(&users2)
+
+
+
+Offset
+db.Offset(3).Find(&users)
+
+
+
+db.Offset(10).Find(&users1).Offset(-1).Find(&users2)
+
+
+
+Count
+db.Where("name = ?", "jinzhu").Or("name = ?", "jinzhu 2").Find(&users).Count(&count)
+
+
+
+db.Model(&User{}).Where("name = ?", "jinzhu").Count(&count)
+
+
+db.Table("deleted_users").Count(&count)
+
+
+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
+Get selected attributes as map
+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)
+
+
+db.Select("name, age").Find(&users)
+
+Scan
+Scan results into another struct.
+type Result struct {
+ Name string
+ Age int
+}
+
+var result Result
+db.Table("users").Select("name, age").Where("name = ?", 3).Scan(&result)
+
+
+db.Raw("SELECT name, age FROM users WHERE name = ?", 3).Scan(&result)
+
+Scopes
+func AmountGreaterThan1000(db *gorm.DB) *gorm.DB {
+ return db.Where("amount > ?", 1000)
+}
+
+func PaidWithCreditCard(db *gorm.DB) *gorm.DB {
+ return db.Where("pay_mode_sign = ?", "C")
+}
+
+func PaidWithCod(db *gorm.DB) *gorm.DB {
+ return db.Where("pay_mode_sign = ?", "C")
+}
+
+func OrderStatus(status []string) func (db *gorm.DB) *gorm.DB {
+ return func (db *gorm.DB) *gorm.DB {
+ return db.Scopes(AmountGreaterThan1000).Where("status in (?)", status)
+ }
+}
+
+db.Scopes(AmountGreaterThan1000, PaidWithCreditCard).Find(&orders)
+
+
+db.Scopes(AmountGreaterThan1000, PaidWithCod).Find(&orders)
+
+
+db.Scopes(OrderStatus([]string{"paid", "shipped"})).Find(&orders)
+
+
+Specifying The Table Name
+
+db.Table("deleted_users").CreateTable(&User{})
+
+var deleted_users []User
+db.Table("deleted_users").Find(&deleted_users)
+
+
+db.Table("deleted_users").Where("name = ?", "jinzhu").Delete()
+
+
+Update
+Update All Fields
+Save
will include all fields when perform the Updating SQL, even it is not changed
+db.First(&user)
+
+user.Name = "jinzhu 2"
+user.Age = 100
+db.Save(&user)
+
+
+
+Update Changed Fields
+If you only want to update changed Fields, you could use Update
, Updates
+
+db.Model(&user).Update("name", "hello")
+
+
+
+db.Model(&user).Where("active = ?", true).Update("name", "hello")
+
+
+
+
+db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})
+
+
+
+db.Model(&user).Updates(User{Name: "hello", Age: 18})
+
+
+
+
+db.Model(&user).Updates(User{Name: "", Age: 0, Actived: false})
+
+Update Selected Fields
+If you only want to update or ignore some fields when updating, you could use Select
, Omit
+db.Model(&user).Select("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})
+
+
+db.Model(&user).Omit("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})
+
+
+Update Changed Fields Without Callbacks
+Updating operations above will invoke BeforeUpdate
, AfterUpdate
, Update UpdatedAt timestamp, Save Associations callbacks, if you don't call them, you could use UpdateColumn
, UpdateColumns
+
+db.Model(&user).UpdateColumn("name", "hello")
+
+
+
+db.Model(&user).UpdateColumns(User{Name: "hello", Age: 18})
+
+
+Batch Updates
+Callbacks won't run when do batch updates
+db.Table("users").Where("id IN (?)", []int{10, 11}).Updates(map[string]interface{}{"name": "hello", "age": 18})
+
+
+
+db.Model(User{}).Updates(User{Name: "hello", Age: 18})
+
+
+
+db.Model(User{}).Updates(User{Name: "hello", Age: 18}).RowsAffected
+
+Update with SQL Expression
+DB.Model(&product).Update("price", gorm.Expr("price * ? + ?", 2, 100))
+
+
+DB.Model(&product).Updates(map[string]interface{}{"price": gorm.Expr("price * ? + ?", 2, 100)})
+
+
+DB.Model(&product).UpdateColumn("quantity", gorm.Expr("quantity - ?", 1))
+
+
+DB.Model(&product).Where("quantity > 1").UpdateColumn("quantity", gorm.Expr("quantity - ?", 1))
+
+
+Change Updating Values In Callbacks
+If you want to change updating values in callbacks using BeforeUpdate
, BeforeSave
, you could use scope.SetColumn
, for example:
+func (user *User) BeforeSave(scope *gorm.Scope) (err error) {
+ if pw, err := bcrypt.GenerateFromPassword(user.Password, 0); err == nil {
+ scope.SetColumn("EncryptedPassword", pw)
+ }
+}
+
+
+
+db.Model(&user).Set("gorm:update_option", "OPTION (OPTIMIZE FOR UNKNOWN)").Update("name, "hello")
+
+
+Delete
+
+db.Delete(&email)
+
+
+
+db.Set("gorm:delete_option", "OPTION (OPTIMIZE FOR UNKNOWN)").Delete(&email)
+
+
+Batch Delete
+db.Where("email LIKE ?", "%jinzhu%").Delete(Email{})
+
+
+Soft Delete
+If struct has DeletedAt
field, it will get soft delete ability automatically!
+Then it won't be deleted from database permanently when call Delete
.
+db.Delete(&user)
+
+
+
+db.Where("age = ?", 20).Delete(&User{})
+
+
+
+db.Where("age = 20").Find(&user)
+
+
+
+db.Unscoped().Where("age = 20").Find(&users)
+
+
+
+db.Unscoped().Delete(&order)
+
+
+
+
+