6.1 KiB
Delete Delete a Record When deleting a record, the deleted value needs to have primary key or it will trigger a Batch Delete, for example:
// 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"; Delete with primary key GORM allows to delete objects using primary key(s) with inline condition, it works with numbers, check out Query Inline Conditions for details
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); Delete Hooks GORM allows hooks BeforeDelete, AfterDelete, those methods will be called when deleting a record, refer Hooks for details
func (u *User) BeforeDelete(tx *gorm.DB) (err error) { if u.Role == "admin" { return errors.New("admin user not allowed to delete") } return } Batch Delete The specified value has no primary value, GORM will perform a batch delete, it will delete all matched records
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%"; To efficiently delete large number of records, pass a slice with primary keys to the Delete method.
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); Block Global Delete If you perform a batch delete without any conditions, GORM WON’T run it, and will return ErrMissingWhereClause error
You have to use some conditions or use raw SQL or enable AllowGlobalUpdate mode, for example:
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 Returning Data From Deleted Rows Return deleted data, only works for database support Returning, for example:
// 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}}
Soft Delete
If your model includes a gorm.DeletedAt field (which is included in gorm.Model), it will get soft delete ability automatically!
When calling Delete, the record WON’T be removed from the database, but GORM will set the DeletedAt‘s value to the current time, and the data is not findable with normal Query methods anymore.
// 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; If you don’t want to include gorm.Model, you can enable the soft delete feature like:
type User struct { ID int Deleted gorm.DeletedAt Name string } Find soft deleted records You can find soft deleted records with Unscoped
db.Unscoped().Where("age = 20").Find(&users) // SELECT * FROM users WHERE age = 20; Delete permanently You can delete matched records permanently with Unscoped
db.Unscoped().Delete(&order) // DELETE FROM orders WHERE id=10; Delete Flag By default, gorm.Model uses *time.Time as the value for the DeletedAt field, and it provides other data formats support with plugin gorm.io/plugin/soft_delete
INFO when creating unique composite index for the DeletedAt field, you must use other data format like unix second/flag with plugin gorm.io/plugin/soft_delete‘s help, e.g:
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 Second
Use unix second as delete flag
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; You can also specify to use milli or nano seconds as the value, for example:
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; Use 1 / 0 AS Delete Flag 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; Mixed Mode Mixed mode can use 0, 1 or unix seconds to mark data as deleted or not, and save the deleted time at the same time.
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; GitHub tag (latest SemVer)