简体   繁体   中英

Select exists with GORM

I want to check if a row exists in a database table or not. I first used this approach:

type MyStruct struct {
    ID    uint32
    Key   string
    Value string
}

var result MyStruct

err := db.
    Where("id = ? AND `key` = ? AND `value` = 0", myID, myKey).
    First(&result).
    Error

if err != nil {
    if err == gorm.ErrRecordNotFound {
        logrus.Error("ErrRecordNotFound")
    }
    logrus.Errorf("Other DB error: %s", err.Error())
}

But I want to achieve this by writing a raw SQL. I tried following:

var result bool

db.Raw("SELECT EXISTS(SELECT 1 FROM my_table WHERE id = ? AND `key` = ? AND `value` = ?)",
    myID, myKey, "0").Scan(&result)

But I get this error:

unsupported destination, should be slice or struct.

I also tried to use method Exec and got the same error.

Note that the variable db is a *gorm.DB instance.

If you want to avoid the ErrRecordNotFound error, you could use Find like db.Limit(1).Find(&user), the Find method accepts both struct and slice data

r := db.
    Where("id = ? AND `key` = ? AND `value` = 0", myID, myKey).
    Limit(1).
    Find(&result)

r.Error
// handle error

exists := r.RowsAffected > 0

Your result should be either a struct or a slice, not a bool. More information at here: https://gorm.io/docs/sql_builder.html#Raw-SQL

This should work:

var result struct {
  Found bool
}

db.Raw("SELECT EXISTS(SELECT 1 FROM my_table WHERE id = ? AND `key` = ? AND `value` = ?) AS found",
    myID, myKey, "0").Scan(&result)

Another way you might check for existence is using Count :

count := int64(0)
err := db.Model(&MyStruct{}).
    Where("id = ? AND key = ? AND value = 0", myID, myKey).
    Count(&count).
    Error
// handle error
exists := count > 0

maybe a late reply, but I wanna share the answer which I found, it's possible to scan directly into a bool. Name of the variable should be changed to a capital letter to achieve this.

ex:

var Found bool

db.Raw("SELECT EXISTS(SELECT 1 FROM magic_table WHERE magic_field1 = ? AND magic_field2 = ? AND magic_field3 = ?) AS found",
    valOfMagicField1, valOfMagicField2, valOfMagicField3).Scan(&Found)   

You can try the following approach

var exists bool
err = db.Model(model).
         Select("count(*) > 0").
         Where("id = ?", id).
         Find(&exists).
         Error

For me trying this with find did not work, the best approach I found is as follows:

    res := db.Model(&MyStruct{}).
        Where("id = ? AND key = ? AND value = 0", myID, myKey).
        First(&result)

    if errors.Is(res.Error, gorm.ErrRecordNotFound) {
      // user does not exists
    } else if res.Error != nil {
      // some other problem
        return res.Error
    }

That should work:

var result bool


db.Raw("SELECT true FROM my_table WHERE id = ? AND key = ? AND value = ?)",
    myID, myKey, "0").Scan(&result)

if result {
  // exists
} else {
  // does not exist
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM