はじめに
こんにちは。某学校でプログラミング等の勉強中のサーバーサイドのプログラマーのワタタクです。
さて今回は「Go言語を真剣に勉強してみた〜データベース接続(MySQL)編〜」と言うことで「Goでのデータベースについての扱い方」について見ていきましょう。
では、早速いってみましょう
「Go言語を真剣に勉強してみた〜基本構文編①(変数、定数、条件分岐、繰り返し処理)〜」についてはこちらから。
「Go言語を真剣に勉強してみた〜基本構文編②(配列)〜」についてはこちらから。
「Go言語を真剣に勉強してみた〜基本構文編③(関数)〜」についてはこちらから。
「Go言語を真剣に勉強してみた〜基本構文編④(ポインタ、構造体)〜」についてはこちらから。
「Go言語を真剣に勉強してみた〜パッケージ編〜」についてはこちらから。
概要
Go言語でデータベースにアクセスするには、sql.DBを使います。この型を使用することで、ステートメントやトランザクションを生成し、クエリを実行し、結果を取得することができます。
最初に知っておくべきこととして、sql.DBはデータベース接続ではないということです。
インポート
以下の二つをインポートして下さい。
• "database/sql"
• _ "github.com/go-sql-driver/mysql"
ドライバをブランクインポートしていることに注意してください。
パッケージ修飾子を_へとエイリアスすることで、あなたのコードからはエクスポートされた名前は見えません。
その中では、ドライバがdatabase/sqlパッケージに対して自身を利用可能として登録します。しかし通常は他には何も起こりません。
データベースアクセス
sql.Open("mysql", "ユーザ名:パスワード@tcp(ホスト名:ポート番号)/データベース名")
//通常:ポート番号3306(筆者はMAMPでのデータベースサーバを使っているためポート番号8889)
*database/sqlの操作には常にエラー処理が必要
データベースが利用可能でアクセス可能かどうか、すぐに確認したい場合は**db.Ping()**を使ってください。その際はエラーチェックを忘れないでください。
作業終了後には、データベースを **Close()**するのが普通。
*defer:特定の処理を関数の一番最後に実行することができます。=遅延実行
db, err := sql.Open("mysql", "scott:tiger@tcp(127.0.0.1:8889)/wp32scott")
if err != nil {
log.Fatal(err)
}
err = db.Ping()
if err != nil {
fmt.Println("データベース接続失敗")
}
defer db.Close()
参照系(SELECT)
全件処理
⒈テーブルのカラム名の変数をすべて用意。(構造体を作ってもよい)
⒉**db.Query("SELECT文")でクエリーを送信。
⒊⒉の戻り値をClose()する。
⒋⒉の戻り値のNext()を使って、行セットに対して繰り返し処理する。
⒌各行において⒉の戻り値のScan(&⒈の変数, ・・・)**でカラムを変数を読み込んでいく
var (
deptno int
dname string
loc string
)
rows, err := db.Query("SELECT * FROM dept")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
err := rows.Scan(&deptno, &dname, &loc)
if err != nil {
log.Fatal(err)
}
//結果
fmt.Println(deptno, dname, loc)
}
主キー検索
⒈テーブルのカラム名の変数をすべて用意。(構造体を作ってもよい)
⒉**db.Prepare("SELECT文")でSQL発行
⒊⒉の戻り値をQueryRow(パラメータ)**する。
var (
deptno int
dname string
loc string
)
stmt, err := db.Prepare("SELECT * FROM dept WHERE deptno = ?")
if err != nil {
log.Fatal(err)
}
err = stmt.QueryRow(10).Scan(&deptno, &dname, &loc)
if err != nil {
log.Fatal(err)
}
fmt.Println(deptno, dname, loc)
更新系(INSERT,UPDATE,DELETE)
⒈**db.Prepare("INSERT,UPDATE,DELETE文")でSQL発行
⒉⒈の戻り値のExec(パラメータ)**で実行。
/*
*INSERT
*/
stmt, err := db.Prepare("INSERT INTO dept(deptno, dname, loc) VALUES(?, ?, ?)")
if err != nil {
log.Fatal(err)
}
res, err := stmt.Exec(50, "WATATAKU", "JAPAN")
if err != nil {
log.Fatal(err)
}
rowCnt, err := res.RowsAffected() // 影響を受けた行数
if err != nil {
log.Fatal(err)
}
log.Printf("%d件追加しました", rowCnt)
/*
*UPDATE
*/
stmt, err := db.Prepare("UPDATE dept SET dname=?,loc=? WHERE deptno=?")
if err != nil {
log.Fatal(err)
}
res, err := stmt.Exec("KAWAAI", "KORIA", 50)
if err != nil {
log.Fatal(err)
}
rowCnt, err := res.RowsAffected() // 影響を受けた行数
if err != nil {
log.Fatal(err)
}
log.Printf("%d件更新しました", rowCnt)
/*
*DELETE
*/
stmt, err := db.Prepare("DELETE FROM dept WHERE deptno=?")
if err != nil {
log.Fatal(err)
}
res, err := stmt.Exec(50)
if err != nil {
log.Fatal(err)
}
rowCnt, err := res.RowsAffected() // 影響を受けた行数
if err != nil {
log.Fatal(err)
}
log.Printf("%d件削除しました", rowCnt)
トランザクション
SQL発行前にBigin()し、各エラーに入るたびにRollback()成功すればCommit()。
tr, err := db.Bigin()
if err != nil {
//エラー
}
//この下からエラーに入るたびに
tr.Rollback()
//成功すれば
tr.Commit()
以上。
もし何か間違っている等のご指摘があればご連絡ください。
最後まで読んで頂きありがとうございました。
次回はまだ未定ですが多分「Go言語を真剣に勉強してみた〜WEBアプリケーション開発編〜」かな???