GORM でよく使う SQL の書き方をメモとして残しておきます。詳細は記事最後の参考リンクの公式ドキュメントで確認できます。
Create
insert
するだけであれば create
を利用します。
// Create
db.Create(&models.User{Name: "user"})
実行SQL
// Create
INSERT INTO "users" ("created_at","updated_at","name","email") VALUES ('2020-04-25 11:22:00','2020-04-25 11:22:00','user',0);
Update
特定のフィールドだけ更新したい場合、 Update
または Updates
を使います。
Update
1カラムだけアップデートします。
// Create
user := &models.User{Name: "user"}
db.Create(user)
// Update
db.Model(user).Update("name", "user2")
実行SQL
// Create
INSERT INTO "users" ("created_at","updated_at","name","email") VALUES ('2020-04-25 11:34:39','2020-04-25 11:34:39','user','');
// Update
UPDATE "users" SET "name" = 'user2', "updated_at" = '2020-04-25 11:34:39' WHERE "users"."id" = 5;
Updates
Updates
は map を利用して複数のフィールドをアップデートします。
// Create
user := &models.User{Name: "user"}
db.Create(user)
// Updates
db.Model(user).Updates(map[string]interface{}{
"name": "user3",
"email": "g5.taisa831@gmail.com",
}
)
実行SQL
// Create
INSERT INTO "users" ("created_at","updated_at","name","email") VALUES ('2020-04-25 11:39:52','2020-04-25 11:39:52','user','');
// Updates
UPDATE "users" SET "email" = 'g5.taisa831@gmail.com', "name" = 'user3', "updated_at" = '2020-04-25 11:39:52' WHERE "users"."id" = 6;
Save
Save
は SQL を実行する際にすべてのフィールドを含みます。フィールドを指定しなくても空にはなりません。また、レコードが存在しない場合は insert
になります(実質 FirstOrCreate
の振る舞いとなる)
// Create
user := &models.User{
Name: "user",
Email: "g5.taisa831@gmail.com"
}
db.Create(user)
// Save
user.Name = "user2"
db.Save(user)
実行SQL
// Create
INSERT INTO "users" ("created_at","updated_at","name","email") VALUES ('2020-04-25 11:43:30','2020-04-25 11:43:30','user','g5.taisa831@gmail.com');
// Save
UPDATE "users" SET "created_at" = '2020-04-25 11:43:30', "updated_at" = '2020-04-25 11:43:30', "name" = 'user2', "email" = 'g5.taisa831@gmail.com' WHERE "users"."id" = 8;
Read
1レコードだけ取得するには First
を利用します。
// Create
user := &models.User{
Name: "user",
Email: "g5.taisa831@gmail.com"
}
db.Create(user)
// First
db.First(user, "name = ?", "user")
// Where句付きFirst
db.Where("name = ?", "user").First(user)
実行SQL
// Create
INSERT INTO "users" ("created_at","updated_at","name","email") VALUES ('2020-04-25 11:48:25','2020-04-25 11:48:25','user','g5.taisa831@gmail.com')
// First
SELECT * FROM "users" WHERE "users"."id" = 10 AND ((name = 'user')) ORDER BY "users"."id" ASC LIMIT 1
// Where句付きFirst
SELECT * FROM "users" WHERE "users"."id" = 10 AND ((name = 'user')) ORDER BY "users"."id" ASC LIMIT 1
Join
join
のサンプルは下記となります。
// Create user
user := &models.User{Name: "user", Email: "g5.taisa831@gmail.com"}
db.Create(user)
// Create post
post := &models.Post{ Post: "post", UserId: user.ID, }
db.Create(post)
// Join user, post
var users []models.User
db.Table("users").
Select("users.*, posts.*").
Joins("inner join posts on users.id = posts.user_id").
Find(&users)
実行SQL
// Create user
INSERT INTO "users" ("created_at","updated_at","name","email") VALUES ('2020-04-25 12:26:39','2020-04-25 12:26:39','user','g5.taisa831@gmail.com')
// Create post
INSERT INTO "posts" ("created_at","updated_at","user_id","post") VALUES ('2020-04-25 12:26:39','2020-04-25 12:26:39',14,'post')
// Join user, post
SELECT users.*, posts.* FROM "users" INNER JOIN posts ON users.id = posts.user_id;
Preload
User モデルに Posts を追加すると Preload
が利用できます。Preload
を利用すると Join
せずに関連レコードが取得できます。下記のような JSON
を返したいときに便利です。
`users {
"id": "1",
"name": "user",
"posts" [
{},
{},
{},
{},
]
}`
type User struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
Posts Post
Name string
Email string
}
type Post struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
UserId uint
Post string
}
// Preload
user := &models.User{
Name: "user",
Email: "g5.taisa831@gmail.com"
}
db.Preload("Posts").Find(&user)`
実行SQL
// Preload
SELECT * FROM "users" WHERE "users"."id" = 16;
SELECT * FROM "posts" WHERE ("user_id" IN (16));