【Golang】データベース操作 sqlite3
Golangの基礎学習〜Webアプリケーション作成までの学習を終えたので、復習を兼ねてまとめていく。 基礎〜応用まで。
package main
/*
sqliteをインストールする際の手順の確認
PostgreSQL は次回。ほぼ同じだが。
インストール済
https://qiita.com/__init__/items/2edfc7acf11234e5b1aa
Mac
# brew のインストール
-> https://brew.sh/index_ja
# sqlite3 をインストール
brew install sqlite
Install gcc C言語のライブラリをインポートするので、GOがビルドする際に必要
-> https://developer.apple.com/xcode
# ドライバのインストール
go get github.com/mattn/go-sqlite3
# 不要だが一応
export CGO_ENABLED=1
Windows
Install sqlite3
-> https://www.sqlite.org/download.html
Install gcc
-> http://tdm-gcc.tdragon.net/
# ドライバのインストール
go get github.com/mattn/go-sqlite3
# 不要だが一応
set CGO_ENABLED=1
macでバージョン確認
# sqlite3 インストール確認
$ sqlite3
SQLite version 3.19.3 2017-06-27 16:48:08
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite>
# sqlite3 を抜ける
sqlite> .exit
# xcode のコマンドラインツールの確認
$ xcode-select --install
xcode-select: error: command line tools are already installed, use "Software Update" to install updates
# gcc インストール確認
$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 10.0.0 (clang-1000.11.45.5)
Target: x86_64-apple-darwin17.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
//データベース操作
*/
import (
"database/sql"
"fmt"
"log"
//インポート _にしないとコンパイルエラーになる。使用しない為
_ "github.com/mattn/go-sqlite3"
)
var DbConnection *sql.DB
type Person struct {
Name string
Age int
}
func main() {
//1
//DBを開く なければ作成される
DbConnection, _ := sql.Open("sqlite3", "./example.sql")
//終わったら閉じる
defer DbConnection.Close()
//DB作成 SQLコマンド
cmd := `CREATE TABLE IF NOT EXISTS person(
name STRING,
age INT)`
//実行 結果は返ってこない為、_にする
_, err := DbConnection.Exec(cmd)
//エラーハンドリング
if err != nil {
fmt.Println("エラー")
log.Fatalln(err)
}
//ターミナル
//sqlite3
//.table
//SELECT * FROM tablename;
//で確認
//2 CRUD処理
//Create
//データを追加
//VALUES (?, ?) 値は後で渡す。セキュリテイの関係でこのようにする方がいい
//SQLインジェクション 悪意あるコマンドでDBが操作されてしまうのを防ぐ ?でエスケープしてくれる
cmd = "INSERT INTO person (name, age) VALUES (?, ?)"
//実行
//レコードを取得する必要のない、クエリはExecメソッドを使う
//第二引数からは、コマンド?部の値
_, err = DbConnection.Exec(cmd, "Nancy", 20)
if err != nil {
log.Fatalln(err)
}
//Update
//データの更新 Mike が存在する場合
cmd = "UPDATE person SET age = ? WHERE name = ?"
_, err = DbConnection.Exec(cmd, 25, "Mike")
if err != nil {
log.Fatalln(err)
}
//Read
//Get All
//マルチセレクト
//データ全てをループで表示
//Queryは全て取得する
cmd = "SELECT * FROM person"
rows, _ := DbConnection.Query(cmd)
defer rows.Close()
//structを作成
var pp []Person
//取得したデータをループでスライスに追加 for rows.Next()
for rows.Next() {
var p Person
//scan データ追加
err := rows.Scan(&p.Name, &p.Age)
if err != nil {
log.Println(err)
}
pp = append(pp, p)
}
err = rows.Err()
if err != nil {
log.Fatalln(err)
}
//表示
for _, p := range pp {
fmt.Println(p.Name, p.Age)
}
//特定のデータを取得
cmd = "SELECT * FROM person where age = ?"
//age = 20にして実行
//QueryRowは最初の一件だけ取得する。
row := DbConnection.QueryRow(cmd, 20)
var p Person
err = row.Scan(&p.Name, &p.Age)
if err != nil {
//データがなかったら
if err == sql.ErrNoRows {
log.Println("No row")
//それ以外のエラー
} else {
log.Println(err)
}
}
fmt.Println(p.Name, p.Age)
//Delete
//データの削除 全て
cmd = "DELETE FROM person WHERE name = ?"
_, err = DbConnection.Exec(cmd, "Nancy")
if err != nil {
log.Fatalln(err)
}
//マルチセレクト テーブルもSQLインジェクション対策
//こちらを推奨
//データを構造体に入れて表示
//テーブルはSQLインジェクション対策が使えない
tableName := "person"
//テーブル名指定は?が使えない為、%sを使う。
//後に対応されるかも?
cmd = fmt.Sprintf("SELECT * FROM %s", tableName)
rows1, _ := DbConnection.Query(cmd)
defer rows1.Close()
var pp1 []Person
//パターンとして覚える
for rows1.Next() {
var p Person
//データを構造体に追加
err := rows1.Scan(&p.Name, &p.Age)
if err != nil {
log.Println(err)
}
//ppに追加
pp1 = append(pp1, p)
}
//まとめてエラーチェック
err = rows1.Err()
if err != nil {
//エラーなら終了
log.Fatalln(err)
}
for _, p := range pp1 {
fmt.Println(p.Name, p.Age)
}
}