Go SQL チートシート
Goの標準ライブラリ「database/sql
」を使ったSQLの基本操作をまとめたチートシートです。簡単な説明とともにコードサンプルを紹介します。
1. インポート & ドライバ設定
import (
"database/sql"
_ "github.com/go-sql-driver/mysql" // 使用するデータベースドライバ(MySQLの場合)をインポート
// _ "github.com/lib/pq" // PostgreSQLの場合はこのように別のドライバをインポート
)
-
database/sql
: Go標準のSQLデータベースインターフェース。 -
_
は、ドライバパッケージを明示的に使用しないが、初期化は行う必要があるために使う。
2. データベースに接続
db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/dbname")
if err != nil {
log.Fatal(err) // エラー発生時にプログラムを終了させる
}
defer db.Close() // 関数終了時に接続を閉じる
-
sql.Open
: データベースへの接続を開始。接続自体はまだ確立されていない。 -
defer db.Close()
: 関数が終了する際にデータベース接続を閉じるための予約。
3. データベースにPingを送る
err = db.Ping()
if err != nil {
log.Fatal(err) // 接続が確立されていない場合、エラーメッセージを表示して終了
}
-
Ping()
: 実際にデータベースに接続して通信ができるか確認する。
4. クエリ実行(SELECT)
4.1 単一行を取得 (QueryRow
)
var name string
err := db.QueryRow("SELECT name FROM users WHERE id = ?", 1).Scan(&name)
if err != nil {
log.Fatal(err) // エラー発生時にエラーメッセージを表示
}
fmt.Println(name) // 取得した名前を表示
-
QueryRow
: 結果が1行のクエリを実行する際に使用。 -
Scan
: データベースから取得した値をGoの変数にマッピング。
4.2 複数行を取得 (Query
)
rows, err := db.Query("SELECT id, name FROM users")
if err != nil {
log.Fatal(err) // クエリ実行時にエラーがあれば終了
}
defer rows.Close() // `rows`は使用後に必ず閉じる
for rows.Next() { // 次の行が存在する限りループを実行
var id int
var name string
err := rows.Scan(&id, &name) // カラムの値を変数に格納
if err != nil {
log.Fatal(err) // エラーが発生した場合終了
}
fmt.Printf("ID: %d, Name: %s\n", id, name) // 取得したデータを表示
}
if err := rows.Err(); err != nil { // クエリ中のエラーチェック
log.Fatal(err)
}
-
Query
: 複数行を取得する際に使用。 -
rows.Next()
: 次の行が存在するか確認してループを継続。 -
Scan
: 各行のカラムを変数にマッピング。
5. データ挿入 (INSERT)
result, err := db.Exec("INSERT INTO users (name, age) VALUES (?, ?)", "Alice", 30)
if err != nil {
log.Fatal(err) // 挿入時にエラーがあれば終了
}
lastInsertID, err := result.LastInsertId() // 最後に挿入された行のIDを取得
if err != nil {
log.Fatal(err) // エラーがあれば終了
}
fmt.Println("Last Insert ID:", lastInsertID) // 挿入したレコードのIDを表示
-
Exec
: データベースの変更系操作(INSERT, UPDATE, DELETE)に使用。 -
LastInsertId
: 挿入した行のIDを取得する。
6. データ更新 (UPDATE)
result, err := db.Exec("UPDATE users SET age = ? WHERE id = ?", 31, 1)
if err != nil {
log.Fatal(err) // 更新時にエラーがあれば終了
}
rowsAffected, err := result.RowsAffected() // 更新された行数を取得
if err != nil {
log.Fatal(err) // エラーがあれば終了
}
fmt.Println("Rows Affected:", rowsAffected) // 更新された行数を表示
-
RowsAffected
: 更新された行数を取得できる。
7. データ削除 (DELETE)
result, err := db.Exec("DELETE FROM users WHERE id = ?", 1)
if err != nil {
log.Fatal(err) // 削除時にエラーがあれば終了
}
rowsAffected, err := result.RowsAffected() // 削除された行数を取得
if err != nil {
log.Fatal(err) // エラーがあれば終了
}
fmt.Println("Rows Affected:", rowsAffected) // 削除された行数を表示
- DELETEクエリも
Exec
で実行し、影響を受けた行数を確認。
8. トランザクション処理
tx, err := db.Begin() // トランザクションの開始
if err != nil {
log.Fatal(err) // エラーがあれば終了
}
_, err = tx.Exec("UPDATE accounts SET balance = balance - 100 WHERE id = ?", 1) // 口座1から100を減額
if err != nil {
tx.Rollback() // エラー発生時はトランザクションをロールバック
log.Fatal(err)
}
_, err = tx.Exec("UPDATE accounts SET balance = balance + 100 WHERE id = ?", 2) // 口座2に100を加算
if err != nil {
tx.Rollback() // エラー発生時はトランザクションをロールバック
log.Fatal(err)
}
err = tx.Commit() // 成功したらトランザクションを確定
if err != nil {
log.Fatal(err) // コミット時にエラーがあれば終了
}
-
Begin
: トランザクションを開始。 -
Rollback
: エラー時にロールバック。 -
Commit
: トランザクションが正常に完了したらコミットして確定。
9. プリペアドステートメント (Prepared Statements)
stmt, err := db.Prepare("INSERT INTO users (name, age) VALUES (?, ?)")
if err != nil {
log.Fatal(err) // 準備時にエラーがあれば終了
}
defer stmt.Close() // 使用後は必ずクローズ
_, err = stmt.Exec("Bob", 25) // 準備したステートメントでクエリを実行
if err != nil {
log.Fatal(err) // 実行時にエラーがあれば終了
}
_, err = stmt.Exec("Charlie", 29) // 別のデータを実行
if err != nil {
log.Fatal(err) // 実行時にエラーがあれば終了
}
-
Prepare
: 複数回同じクエリを実行する場合に有効。パフォーマンスが向上。 -
Exec
: 準備されたステートメントを実行。
10. Null値の処理
var age sql.NullInt64
err := db.QueryRow("SELECT age FROM users WHERE id = ?", 1).Scan(&age)
if err != nil {
log.Fatal(err) // クエリ実行時にエラーがあれば終了
}
if age.Valid {
fmt.Println("Age:", age.Int64) // NULLでない場合、値を表示
} else {
fmt.Println("Age is NULL") // NULLの場合は「NULL」と表示
}
-
sql.NullInt64
やsql.NullString
などを使って、データベースのNULL値を扱うことができる。 -
Valid
フィールドで、値がNULLかどうかを確認する。