刪除

刪除記錄

刪除記錄時,已刪除的值需要有主鍵,否則會觸發批次刪除,例如

// Email's ID is `10`
db.Delete(&email)
// DELETE from emails where id = 10;

// Delete with additional conditions
db.Where("name = ?", "jinzhu").Delete(&email)
// DELETE from emails where id = 10 AND name = "jinzhu";

使用主鍵刪除

GORM 允許使用內嵌條件刪除具有主鍵的物件,它適用於數字,請查看查詢內嵌條件以取得詳細資訊

db.Delete(&User{}, 10)
// DELETE FROM users WHERE id = 10;

db.Delete(&User{}, "10")
// DELETE FROM users WHERE id = 10;

db.Delete(&users, []int{1,2,3})
// DELETE FROM users WHERE id IN (1,2,3);

刪除掛鉤

GORM 允許掛鉤BeforeDeleteAfterDelete,這些方法會在刪除記錄時呼叫,請參閱掛鉤以取得詳細資訊

func (u *User) BeforeDelete(tx *gorm.DB) (err error) {
if u.Role == "admin" {
return errors.New("admin user not allowed to delete")
}
return
}

批次刪除

指定的值沒有主鍵值,GORM 會執行批次刪除,它會刪除所有符合的記錄

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%";

若要有效率地刪除大量記錄,請傳遞包含主鍵的區段給Delete方法。

var users = []User{{ID: 1}, {ID: 2}, {ID: 3}}
db.Delete(&users)
// DELETE FROM users WHERE id IN (1,2,3);

db.Delete(&users, "name LIKE ?", "%jinzhu%")
// DELETE FROM users WHERE name LIKE "%jinzhu%" AND id IN (1,2,3);

封鎖全域刪除

如果您在沒有任何條件的情況下執行批次刪除,GORM 將不會執行它,並會傳回ErrMissingWhereClause錯誤

您必須使用一些條件或使用原始 SQL 或啟用AllowGlobalUpdate模式,例如

db.Delete(&User{}).Error // gorm.ErrMissingWhereClause

db.Delete(&[]User{{Name: "jinzhu1"}, {Name: "jinzhu2"}}).Error // gorm.ErrMissingWhereClause

db.Where("1 = 1").Delete(&User{})
// DELETE FROM `users` WHERE 1=1

db.Exec("DELETE FROM users")
// DELETE FROM users

db.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&User{})
// DELETE FROM users

從已刪除列傳回資料

傳回已刪除資料,僅適用於支援傳回的資料庫,例如

// return all columns
var users []User
DB.Clauses(clause.Returning{}).Where("role = ?", "admin").Delete(&users)
// DELETE FROM `users` WHERE role = "admin" RETURNING *
// users => []User{{ID: 1, Name: "jinzhu", Role: "admin", Salary: 100}, {ID: 2, Name: "jinzhu.2", Role: "admin", Salary: 1000}}

// return specified columns
DB.Clauses(clause.Returning{Columns: []clause.Column{{Name: "name"}, {Name: "salary"}}}).Where("role = ?", "admin").Delete(&users)
// DELETE FROM `users` WHERE role = "admin" RETURNING `name`, `salary`
// users => []User{{ID: 0, Name: "jinzhu", Role: "", Salary: 100}, {ID: 0, Name: "jinzhu.2", Role: "", Salary: 1000}}

軟刪除

如果您的模型包含一個 gorm.DeletedAt 欄位(包含在 gorm.Model 中),它將自動獲得軟刪除功能!

呼叫 Delete 時,記錄將不會從資料庫中移除,但 GORM 會將 DeletedAt 的值設定為目前時間,而且資料將無法再透過一般的查詢方法找到。

// user's ID is `111`
db.Delete(&user)
// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE id = 111;

// Batch Delete
db.Where("age = ?", 20).Delete(&User{})
// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE age = 20;

// Soft deleted records will be ignored when querying
db.Where("age = 20").Find(&user)
// SELECT * FROM users WHERE age = 20 AND deleted_at IS NULL;

如果您不想要包含 gorm.Model,您可以像這樣啟用軟刪除功能

type User struct {
ID int
Deleted gorm.DeletedAt
Name string
}

尋找軟刪除的記錄

您可以使用 Unscoped 尋找軟刪除的記錄

db.Unscoped().Where("age = 20").Find(&users)
// SELECT * FROM users WHERE age = 20;

永久刪除

您可以使用 Unscoped 永久刪除符合條件的記錄

db.Unscoped().Delete(&order)
// DELETE FROM orders WHERE id=10;

刪除標記

預設情況下,gorm.Model 使用 *time.Time 作為 DeletedAt 欄位的數值,並且透過外掛 gorm.io/plugin/soft_delete 提供其他資料格式支援

資訊當您為 DeletedAt 欄位建立唯一的複合索引時,您必須使用其他資料格式,例如 Unix 秒數/標記,並透過外掛 gorm.io/plugin/soft_delete 的協助,例如

import "gorm.io/plugin/soft_delete"

type User struct {
ID uint
Name string `gorm:"uniqueIndex:udx_name"`
DeletedAt soft_delete.DeletedAt `gorm:"uniqueIndex:udx_name"`
}

Unix 秒數

使用 Unix 秒數作為刪除標記

import "gorm.io/plugin/soft_delete"

type User struct {
ID uint
Name string
DeletedAt soft_delete.DeletedAt
}

// Query
SELECT * FROM users WHERE deleted_at = 0;

// Delete
UPDATE users SET deleted_at = /* current unix second */ WHERE ID = 1;

您也可以指定使用 millinano 秒數作為數值,例如

type User struct {
ID uint
Name string
DeletedAt soft_delete.DeletedAt `gorm:"softDelete:milli"`
// DeletedAt soft_delete.DeletedAt `gorm:"softDelete:nano"`
}

// Query
SELECT * FROM users WHERE deleted_at = 0;

// Delete
UPDATE users SET deleted_at = /* current unix milli second or nano second */ WHERE ID = 1;

使用 1 / 0 作為刪除標記

import "gorm.io/plugin/soft_delete"

type User struct {
ID uint
Name string
IsDel soft_delete.DeletedAt `gorm:"softDelete:flag"`
}

// Query
SELECT * FROM users WHERE is_del = 0;

// Delete
UPDATE users SET is_del = 1 WHERE ID = 1;

混合模式

混合模式可以使用 01 或 Unix 秒數來標記資料是否已刪除,並同時儲存刪除時間。

type User struct {
ID uint
Name string
DeletedAt time.Time
IsDel soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt"` // use `1` `0`
// IsDel soft_delete.DeletedAt `gorm:"softDelete:,DeletedAtField:DeletedAt"` // use `unix second`
// IsDel soft_delete.DeletedAt `gorm:"softDelete:nano,DeletedAtField:DeletedAt"` // use `unix nano second`
}

// Query
SELECT * FROM users WHERE is_del = 0;

// Delete
UPDATE users SET is_del = 1, deleted_at = /* current unix second */ WHERE ID = 1;

白金贊助商

金牌贊助商

白金贊助商

金牌贊助商