Search code examples
goormgo-gorm

How to Create or Update a record with GORM?


Gorm has a FirstOrCreate method and a FirstOrInit but how to check afterwards if the record was actually created? I like to create a record if it does not exists and if it exists I want to update some fields.


Solution

  • update 2020.10.09

    Thanks for @vaelin

    From 1.20.x on, GORM provides compatible Upsert support for different databases( Upsert-On-Conflict)

    // Update columns to new value on `id` conflict
    DB.Clauses(clause.OnConflict{
      Columns:   []clause.Column{{Name: "id"}}, // key colume
      DoUpdates: clause.AssignmentColumns([]string{"name", "age"}), // column needed to be updated
    }).Create(&users)
    // MERGE INTO "users" USING *** WHEN NOT MATCHED THEN INSERT *** WHEN MATCHED THEN UPDATE SET "name"="excluded"."name"; SQL Server
    // INSERT INTO "users" *** ON CONFLICT ("id") DO UPDATE SET "name"="excluded"."name", "age"="excluded"."age"; PostgreSQL
    // INSERT INTO `users` *** ON DUPLICATE KEY UPDATE `name`=VALUES(name),`age=VALUES(age); MySQL
    

    With gorm 1.9.x or below, it's more effecient to update first, then insert when not existed.

    // update only set name=nick
    if err := db.Model(&newUser).Where("id = ?", 3333).Update("name", "nick").Error; err != nil {
        // always handle error like this, cause errors maybe happened when connection failed or something. 
        // record not found...
        if gorm.IsRecordNotFoundError(err){
            db.Create(&newUser)  // create new record from newUser
        }
    }
    

    FirstOrInit and FirstOrCreate are different. If there is no match record in database, FirstOrInit will init struct but not create record, FirstOrCreate will create a record and query that record to struct.