sqlite3【Go】
go-sqlite3を使用します。
事前準備は
sqlite3を使用する前の準備【Go】 - 技術向上
に記載しています。
CREATE
var DbConnection *sql.DB func main() { DbConnection, err := sql.Open("sqlite3", "./example.sql") // 第1引数はDriver、第2引数はデータベース名 if err != nil { log.Fatalln(err) } defer DbConnection.Close() // 必ず閉じる // バッククォートを使うことで複数行記載できる // 主キーにidを設定。INTではなくINTEGERである必要がある cmd := `CREATE TABLE IF NOT EXISTS person ( id INTEGER primary key, name STRING, age INT)` _, err = DbConnection.Exec(cmd) // 戻り値resultは使用しないため破棄 if err != nil { log.Fatalln(err) } }
上記作成したテーブルは、下記コマンドで確認できます。
sqlite> .table // テーブル一覧を取得 sqlite> .schema // 全テーブルの構造を取得 sqlite> .schema person // テーブルpersonの構造を取得
INSERT
var DbConnection *sql.DB func main() { DbConnection, err := sql.Open("sqlite3", "./example.sql") // 第1引数はDriver、第2引数はデータベース名 if err != nil { log.Fatalln(err) } defer DbConnection.Close() // 必ず閉じる cmd := `INSERT INTO person (name, age) VALUES (?, ?)` // SQLInjectionを回避するため、後から指定するものはPrintfではなく、?で指定 _, err = DbConnection.Exec(cmd, "Mike", 25) if err != nil { log.Fatalln(err) } }
コマンドで、テーブルの中身を検索できます。
sqlite> select * from person;
UPDATE
var DbConnection *sql.DB func main() { DbConnection, err := sql.Open("sqlite3", "./example.sql") // 第1引数はDriver、第2引数はデータベース名 if err != nil { log.Fatalln(err) } defer DbConnection.Close() // 必ず閉じる cmd := `UPDATE person SET age = ? WHERE name = ?` _, err = DbConnection.Exec(cmd, 26, "Mike") if err != nil { log.Fatalln(err) } }
DELETE
var DbConnection *sql.DB func main() { DbConnection, err := sql.Open("sqlite3", "./example.sql") // 第1引数はDriver、第2引数はデータベース名 if err != nil { log.Fatalln(err) } defer DbConnection.Close() // 必ず閉じる cmd := `DELETE FROM person WHERE name = ?` _, err = DbConnection.Exec(cmd, "Mike") if err != nil { log.Fatalln(err) } }
SELECT
対象のもの全てを抽出するパターン
var DbConnection *sql.DB type Person struct { ID int Name string Age int } func main() { DbConnection, err := sql.Open("sqlite3", "./example.sql") // 第1引数はDriver、第2引数はデータベース名 if err != nil { log.Fatalln(err) } defer DbConnection.Close() // 必ず閉じる cmd := `SELECT * FROM person WHERE age = ?` rows, err := DbConnection.Query(cmd, 26) // 対象全件取得の場合は、Queryを使用 defer rows.Close() var pp []Person if err != nil { log.Fatalln(err) } for rows.Next() { var p Person // 取得結果1件ずつを格納する入れ物を用意 _ = rows.Scan(&p.ID, &p.Name, &p.Age) // Scan()の中身に結果をコピー(値変更のためポインタ渡し)。返り値errorは使用しないため、破棄。forループ終了後、まとめてエラー処理をする pp = append(pp, p) } err = rows.Err() // forループ終了後にまとめてエラーハンドリング if err != nil { log.Fatalln(err) } for _, v := range pp { fmt.Println(v) } }
対象のものから最初の1件を抽出するパターン
var DbConnection *sql.DB type Person struct { ID int Name string Age int } func main() { DbConnection, err := sql.Open("sqlite3", "./example.sql") // 第1引数はDriver、第2引数はデータベース名 if err != nil { log.Fatalln(err) } defer DbConnection.Close() // 必ず閉じる cmd := `SELECT * FROM person WHERE age = ?` row := DbConnection.QueryRow(cmd, 26) // 対象1件取得の場合は、QueryRowを使用 var p Person // 取得結果を格納する入れ物を用意 err = row.Scan(&p.ID, &p.Name, &p.Age) // Scan()の中身に結果をコピー(値変更のためポインタ渡し) if err != nil { // 1件でありforループは無いため、ここでエラーハンドリング if err == sql.ErrNoRows { // errorは、取得対象が存在しないことを識別できる log.Println("No row") } else { log.Fatalln(err) } } fmt.Println(p) }
補足 - テーブル名のコード内指定について
仕様上、テーブル名に「?」を使用することが、現時点ではできません。
テーブル名を変数として持たせるには、fmt.Sprintf()を使います。
... var tableName = "person" cmd := fmt.Sprintf(`SELECT * FROM %s`, tableName) rows, err := DbConnection.Query(cmd) ...