🪽
[入門]GoでSQLite3を使いデータベース操作を行ってみる
インストール
今回はgo-sqlite3を利用する
sqlite
-
brew install sqlite
-
sqlite3
下記のような表示となれば ok
SQLite version 3.39.5 2022-10-14 20:58:05
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite>
-
.exit
で抜ける
go-sqlite3
go get github.com/mattn/go-sqlite3
ただし、下記の通り、Go でビルドするにあたり C 言語のライブラリをインポートするため、CGO_ENABLE=1とgcc のコンパイラが必要
既に入っている方は次のセクションをスキップしてください。
go-sqlite3 is cgo package. If you want to build your app using go-sqlite3, you need gcc. However, after you have built and installed go-sqlite3 with go install github.com/mattn/go-sqlite3 (which requires gcc), you can build your app without relying on gcc in future.
Important: because this is a CGO enabled package, you are required to set the environment variable CGO_ENABLED=1 and have a gcc compiler present within your path.
Xcode
- Xcode-リソースからインストールする
-
xcode-select --install
CLI のインストール
私は既にインストールされていたためxcode-select: note: Command line tools are already installed. Use "Software Update" in System Settings or the softwareupdate command line interface to install updates
と表示されました gcc --version
Apple clang version 15.0.0 (clang-1500.0.40.1)
Target: arm64-apple-darwin23.0.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
データベース操作
name と age のカラムを持つデータベースを作成する
- 次のコードを記述
package main
import (
"database/sql"
"log"
_ "github.com/mattn/go-sqlite3" //ビルド時にコンパイルすることでSQLにアクセス出来る
)
var DbConnection *sql.DB
func main(){
DbConnection, _ := sql.Open("sqlite3", "./example.sql")
defer DbConnection.Close()
cmd := `CREATE TABLE IF NOT EXISTS person(
name STRING,
age INT
)`
//cmdを実行する
_, err := DbConnection.Exec(cmd) //データベースの情報を反映する必要はないため、_を使用
if err != nil{
log.Fatalln(err)
}
}
-
go run main.go
を実行
example.sql というファイルができていれば ok -
sqlite3 example.sql
をターミナルで実行 -
sqlite> .table
person
というテーブルが出来ていることを確認する
person テーブルに値を insert する
- person に対して、データを入れていく
一旦はcmd
,err
を上書きする形で実行する。
後にシングルセレクト、マルチセレクトを行いたいため別レコードを 2 つか 3 つほど入れると良いです
func main(){
DbConnection, _ := sql.Open("sqlite3", "./example.sql")
defer DbConnection.Close()
cmd := `CREATE TABLE IF NOT EXISTS person(
name STRING,
age INT
)`
//cmdを実行する
_, err := DbConnection.Exec(cmd) //データベースの情報を反映する必要はないため、_を使用
if err != nil{
log.Fatalln(err)
}
//追加
cmd = "INSERT INTO person (name, age) VALUES (?, ?)" //SQLインジェクション対策
_,err = DbConnection.Exec(cmd, "Finn", 30)
if err != nil{
log.Fatalln(err)
}
}
-
select * from person
で内容を確認
sqlite> select * from person;
Finn|30
Emma|15
Watson|40
レコードの update
先ほどとほぼ同様に行う
- update コマンドを記述
func main(){
DbConnection, _ := sql.Open("sqlite3", "./example.sql")
defer DbConnection.Close()
cmd := `CREATE TABLE IF NOT EXISTS person(
name STRING,
age INT
)`
//cmdを実行する
_, err := DbConnection.Exec(cmd) //データベースの情報を反映する必要はないため、_を使用
if err != nil{
log.Fatalln(err)
}
//追加
cmd = "UPDATE person SET age = ? WHERE name = ?"
_, err = DbConnection.Exec(cmd, 1000, "Finn")
if err != nil{
log.Fatalln(err)
}
}
- select で確認
1000
と変更されていたので ok
マルチセレクト
- cmd をアップデート
func main(){
DbConnection, _ := sql.Open("sqlite3", "./example.sql")
defer DbConnection.Close()
cmd := `CREATE TABLE IF NOT EXISTS person(
name STRING,
age INT
)`
//cmdを実行する
_, err := DbConnection.Exec(cmd) //データベースの情報を反映する必要はないため、_を使用
if err != nil{
log.Fatalln(err)
}
//追加
cmd = "SELECT * FROM person"
rows,_ := DbConnection.Query(cmd)
defer rows.Close()
}
- Person struct を作成する
type Person struct {
Name string
Age int
}
- Person スライスにデータを入れる
func main(){
DbConnection, _ := sql.Open("sqlite3", "./example.sql")
defer DbConnection.Close()
cmd := `CREATE TABLE IF NOT EXISTS person(
name STRING,
age INT
)`
//cmdを実行する
_, err := DbConnection.Exec(cmd) //データベースの情報を反映する必要はないため、_を使用
if err != nil{
log.Fatalln(err)
}
cmd = "SELECT * FROM person"
rows,_ := DbConnection.Query(cmd)
defer rows.Close()
//追加
var pp []Person
for rows.Next(){
var p Person
err := rows.Scan(&p.Name, &p.Age) //アドレスを引数に渡すろstructにデータを入れてくれる
if err != nil{
log.Fatalln(err)
}
pp = append(pp,p)
}
for _,p := range pp {
fmt.Println(p.Name,p.Age)
}
}
- 以下のようなデータが表示されれば ok
Finn 1000
Emma 15
Watson 40
シングルセレクト
- cmd をアップデート
func main(){
DbConnection, _ := sql.Open("sqlite3", "./example.sql")
defer DbConnection.Close()
cmd := `CREATE TABLE IF NOT EXISTS person(
name STRING,
age INT
)`
_, err := DbConnection.Exec(cmd)
if err != nil{
log.Fatalln(err)
}
//追加
cmd = "SELECT * FROM person where age = ?"
row := DbConnection.QueryRow(cmd, 15) //存在しているレコードのageを入力
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)
}
- 実行し、確認
レコードが表示されれば ok
Emma 15
- 存在しないレコードを query した場合
row := DbConnection.QueryRow(cmd, 15)
↓
row := DbConnection.QueryRow(cmd, 9999999)
- エラーが表示されることを確認する
No row
レコードの削除
- コードを更新
func main(){
DbConnection, _ := sql.Open("sqlite3", "./example.sql")
defer DbConnection.Close()
cmd := `CREATE TABLE IF NOT EXISTS person(
name STRING,
age INT
)`
_, err := DbConnection.Exec(cmd)
if err != nil{
log.Fatalln(err)
}
//追加
cmd = "DELETE FROM person WHERE name = ?"
DbConnection.Exec(cmd, "Finn")
if err != nil{
log.Fatalln(err)
}
}
- 対象が消えていれば ok
Discussion