LoginSignup
4
3

More than 5 years have passed since last update.

GoでNULL値含むレコードがDBから取得できないとき

Posted at

sql.NullString(or NullXXX)を使いましょう

stackoverflowにある似たような質問

背景

sqlパッケージのAPIドキュメントのサンプルを参考に値を取ってくるとします。例えばこのようなコードですね。

    age := 27
    rows, err := db.Query("SELECT id, name, address FROM users WHERE age=?", age)
    if err != nil {
            log.Fatal(err)
    }
    defer rows.Close()
    for rows.Next() {
            var id string
            var name string
            var address string
            if err := rows.Scan(&id, &name, &address); err != nil {
                    // もしレコードのどこかにNULL値があれば、errを吐いて終了する。
                    log.Fatal(err)
            }
            fmt.Printf("%s %s %s\n", id, name, address)
    }
    if err := rows.Err(); err != nil {
            log.Fatal(err)
    }

ここでもしnameがNULL値だった場合、errを吐いてこけます。だからNULL値を許容するカラムにはstringではなくsql.NullStringを使いましょうというだけの話なんですが。。。ここでもしrows.Scan()のエラーチェックを省略すると、見かけ上処理が正しく終わったようになってしまうため、ハマってしまうことがあるかと思います。

    age := 27
    rows, err := db.Query("SELECT id, name, address FROM users WHERE age=?", age)
    if err != nil {
            log.Fatal(err)
    }
    defer rows.Close()
    for rows.Next() {
            var id string
            var name string
            var address string

            // 例えば id:"1", name:NULL, address:"Tokyo"というレコードが合った場合、
            // errorチェックを省くと・・・
            // id=1, name=, address=\n
            // が標準出力される。見かけ上、name, addressが空文字だっただけに見える。(実際はaddressにはデータがあるが、Scan()が中断されて取得できていない)
            /*
            if err := rows.Scan(&id, &name, &address); err != nil {
                    log.Fatal(err)
            */
            rows.Scan(&id, &name, &address)           

            fmt.Printf("id=%s name=%s address=%s\n", id, name, address)
    }
    if err := rows.Err(); err != nil {
            log.Fatal(err)
    }

まとめ

  • sql.NullString(NullXXX)使いましょう
  • エラーチェックサボらないようにしましょう
4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3