削除

レコードの削除

レコードを削除する際、削除される値は主キーを持つ必要があり、そうでない場合は一括削除がトリガーされます。例を挙げます。

// 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

削除された行からのデータの返却

削除されたデータを返却します。これはReturningをサポートするデータベースでのみ動作します。例を挙げます。

// 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.ModelDeletedAtフィールドの値として*time.Timeを使用します。また、gorm.io/plugin/soft_deleteプラグインを使用して他のデータ形式もサポートしています。

INFO DeletedAtフィールドに一意の複合インデックスを作成する場合は、gorm.io/plugin/soft_deleteプラグインの助けを借りて、Unix秒/フラグのような他のデータ形式を使用する必要があります。例:

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;

値としてmilliまたはnano秒を使用するように指定することもできます。例を挙げます。

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;

プラチナスポンサー

ゴールドスポンサー

プラチナスポンサー

ゴールドスポンサー