Your Question

Inserting the second user Jack returns the result CompanyID 0.

Name: Bob ➜ CompanyID: 1
Name: Jack ➜ CompanyID: 0

What do I have to do so that the user Jack also receives CompanyID 1? Basically, this is clear, because the company Gopher Inc. already exists through the first insert.

But wouldn't it be better for an UNIQUE constraint failed: companies.name to return the corresponding ID? That would significantly reduce the complexity of the queries. The relations are already defined by the structs. Or am I using the wrong method or the method in a wrong way?

package main

import (
    "fmt"
    "gorm.io/driver/sqlite"
    "gorm.io/gorm"
)

type User struct {
    ID        uint   `gorm:"primaryKey"`
    Name      string `gorm:"unique"`
    CompanyID uint
    Company   Company // Belongs to relationship
}

type Company struct {
    ID   uint   `gorm:"primaryKey"`
    Name string `gorm:"unique"`
}

func (user User) String() string {
    return fmt.Sprintf("Name: %s ➜ CompanyID: %d", user.Name, user.Company.ID)
}

func main() {
    db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{})
    if err != nil {
        panic("failed to connect database")
    }

    db.AutoMigrate(&User{}, &Company{})

    user := User{
        Name: "Bob",
        Company: Company{
            Name: "Gopher Inc.",
        },
    }

    db.Save(&user)

    user = User{
        Name: "Jack",
        Company: Company{
            Name: "Gopher Inc.",
        },
    }

    db.Save(&user)

    var result User
    db.Preload("Company").First(&result, 1)
    fmt.Println(result)

    var result2 User
    db.Preload("Company").First(&result2, 2)
    fmt.Println(result2)
}

The document you expected this should be explained

Expected answer

Comment From: typomedia

It works as expected, when I replace the following code:

// gorm.io/gorm v1.25.9
// on_conflict.go:42
if onConflict.DoNothing {
        builder.WriteString("DO NOTHING")
    } else {
        builder.WriteString("DO UPDATE SET ")
        onConflict.DoUpdates.Build(builder)
    }

in

builder.WriteString("DO UPDATE SET ")
onConflict.DoUpdates.Build(builder)

It looks like, you can't use DO NOTHING clause in combination with RETURNING in SQLite.