search
LoginSignup
5

More than 1 year has passed since last update.

posted at

【Golang】データベース操作 sqlite3

【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)
    }
}

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
What you can do with signing up
5