From e7c4e7de4e85f6f3a24da8fea0f4c785138711be Mon Sep 17 00:00:00 2001 From: Jinzhu Date: Fri, 19 Feb 2016 11:23:08 +0800 Subject: [PATCH] Update README for Updating --- README.md | 97 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 71 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 1c06820e..4d078b87 100644 --- a/README.md +++ b/README.md @@ -47,9 +47,14 @@ go get -u github.com/jinzhu/gorm - [Query Chains](#query-chains) - [Preloading (Eager loading)](#preloading-eager-loading) - [Update](#update) - - [Update Without Callbacks](#update-without-callbacks) + - [Update All Fields](#update-all-fields) + - [Update Changed Fields](#update-changed-fields) + - [Update Selected Fields](#update-selected-fields) + - [Update Changed Fields Without Callbacks](#update-changed-fields-without-callbacks) - [Batch Updates](#batch-updates) - [Update with SQL Expression](#update-with-sql-expression) + - [Change Updating Values In Callbacks](#change-updating-values-in-callbacks) + - [Extra Update option](#extra-update-option) - [Delete](#delete) - [Batch Delete](#batch-delete) - [Soft Delete](#soft-delete) @@ -453,66 +458,86 @@ db.Preload("Orders", "state = ?", "paid").Preload("Orders.OrderItems").Find(&use ## Update +### Update All Fields + +`Save` will include all fields when perform the Updating SQL, even it is not changed + ```go -// Update an existing struct db.First(&user) + user.Name = "jinzhu 2" user.Age = 100 db.Save(&user) -//// UPDATE users SET name='jinzhu 2', age=100, updated_at = '2013-11-17 21:34:10' WHERE id=111; -db.Where("active = ?", true).Save(&user) -//// UPDATE users SET name='jinzhu 2', age=100, updated_at = '2013-11-17 21:34:10' WHERE id=111 AND active = true; +//// UPDATE users SET name='jinzhu 2', age=100, birthday='2016-01-01', updated_at = '2013-11-17 21:34:10' WHERE id=111; +``` -// Update an attribute if it is changed +### Update Changed Fields + +If you only want to update changed Fields, you could use `Update`, `Updates` + +```go +// Update single attribute if it is changed db.Model(&user).Update("name", "hello") -//// UPDATE users SET name='hello', updated_at = '2013-11-17 21:34:10' WHERE id=111; +//// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111; +// Update single attribute with combined conditions 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; +//// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111 AND active=true; -db.First(&user, 111).Update("name", "hello") -//// SELECT * FROM users LIMIT 1; -//// UPDATE users SET name='hello', updated_at = '2013-11-17 21:34:10' WHERE id=111; -// Update multiple attributes if they are changed +// Update multiple attributes with `map`, will only update those changed fields 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; -// Update multiple attributes if they are changed (update with struct only works with none zero values) +// Update multiple attributes with `struct`, will only update those changed & non blank fields 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; -// Add extra SQL option for updating 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); +// WARNING when update with struct, GORM will only update those fields that with non blank value +// For below Update, nothing will be updated as "", 0, false are blank values of their types +db.Model(&user).Updates(User{Name: "", Age: 0, Actived: false}) ``` -### Update Without Callbacks +### Update Selected Fields -By default, update will call BeforeUpdate, AfterUpdate callbacks, if you want to update w/o callbacks and w/o saving associations: +If you only want to update or ignore some fields when updating, you could use `Select`, `Omit` ```go +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; +``` + +### 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` + +```go +// Update single attribute, similar with `Update` db.Model(&user).UpdateColumn("name", "hello") //// UPDATE users SET name='hello' WHERE id = 111; -// Update with struct only works with none zero values, or use map[string]interface{} +// 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; ``` ### Batch Updates +Callbacks won't run when do batch updates + ```go -db.Table("users").Where("id = ?", 10).Updates(map[string]interface{}{"name": "hello", "age": 18}) -//// UPDATE users SET name='hello', age=18 WHERE id = 10; +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); // Update with struct only works with none zero values, or use map[string]interface{} db.Model(User{}).Updates(User{Name: "hello", Age: 18}) //// UPDATE users SET name='hello', age=18; -// Callbacks won't run when do batch updates - -// Use `RowsAffected` to get the count of affected records +// Get updated records count with `RowsAffected` db.Model(User{}).Updates(User{Name: "hello", Age: 18}).RowsAffected ``` @@ -520,10 +545,10 @@ db.Model(User{}).Updates(User{Name: "hello", Age: 18}).RowsAffected ```go DB.Model(&product).Update("price", gorm.Expr("price * ? + ?", 2, 100)) -//// UPDATE "products" SET "code" = 'L1212', "price" = price * '2' + '100', "updated_at" = '2013-11-17 21:34:10' WHERE "id" = '2'; +//// 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 "code" = 'L1212', "price" = price * '2' + '100', "updated_at" = '2013-11-17 21:34:10' WHERE "id" = '2'; +//// 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'; @@ -532,6 +557,26 @@ DB.Model(&product).Where("quantity > 1").UpdateColumn("quantity", gorm.Expr("qua //// UPDATE "products" SET "quantity" = quantity - 1 WHERE "id" = '2' AND 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: + +```go +func (user *User) BeforeSave(scope *gorm.Scope) (err error) { + if pw, err := bcrypt.GenerateFromPassword(user.Password, 0); err == nil { + scope.SetColumn("EncryptedPassword", pw) + } +} +``` + +### Extra Update option + +```go +// Add extra SQL option for updating 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); +``` + ## Delete ```go