🫥
GORMの Pluck で converting NULL to int is unsupported がでたときの対応
Go言語のORMであるGORMでは、selectで複数のレコードを取得する際、任意のカラムだけを取得する方法として、Pluck
が使えます。
例えば、このようにすると、Userの中の idカラムだけを int64のスライスにセットすることができてとても便利です。
// Retrieving ages of all users
var ids []int64
db.Model(&User{}).Pluck("id", &ids)
先日、以下のようなコードを書いて実行したところ、、、
var userIDs []int
result := db.Table("teams").
Joins("LEFT JOIN managers ON managers.team_id = teams.id").
Pluck("managers.user_id", &userIDs)
if result.Error != nil {
log.Fatal(result.Error)
}
sql: Scan error on column index 0, name "user_id": converting NULL to int is unsupported
というエラーが出ました。
これは、取得した結果、user_idカラムがNULLのレコードがあり、int に変換できなかった、ということになります。
対策方法1. LEFT JOIN
をやめる。
LEFT JOIN
の場合、右側のテーブルに一致するレコードがない場合、NULLが返ってきてしまいます。以下のように、INNER JOIN
を使うと、完全に一致するレコードのみ取得されるので、NULLにならないようになります。
var userIDs []int
result := db.Table("teams").
- Joins("LEFT JOIN managers ON managers.team_id = teams.id").
+ Joins("INNER JOIN managers ON managers.team_id = teams.id").
Pluck("managers.user_id", &userIDs)
対策方法2. NULLを変換する。
外部結合にする必要がある場合や、そもそもNULLが許可されたカラムの場合、 MySQLの場合は IFNULL
などを使って、NULLを変換することで回避できます。以下のコードでは、NULLの場合に -1
が返ってきます。
var userIDs []int
result := db.Table("teams").
Joins("LEFT JOIN managers ON managers.team_id = teams.id").
- Pluck("managers.user_id", &userIDs)
+ Pluck("IFNULL(managers.user_id, -1)", &userIDs)
if result.Error != nil {
log.Fatal(result.Error)
}
Discussion