【Goライブラリ】sqlとsqlxを比べてみた

go言語

Go言語でデータベースを扱う時はどのようにすればいいのか?通常のsqlを使う方法とsqlxを使う方法があります。今回は簡単な例を交えて両者の使い勝手を見比べてみましょう。

テスト用structを用意する

以下の商品詳細データのstructがあるとします。

// 商品詳細データのstruct
type ProductDetailData struct {
	ProductDetailDataId int     `db:"productDetailDataId"`
	ProductDataId       int     `db:"productDataId"`
	GrossProfitMargin   float64 `db:"grossProfitMargin"`
	PurchaseDate        string  `db:"purchaseDate"`
	SalesDate           string  `db:"salesDate"`
}

いつものsqlで全データを取得してみよう

import "database/sql"
func getAllProductDetailData () []ProductDetailData {
	db, _ := sql.Open("sqlite3", "./sellManagement.sql")
	defer db.Close()
	cmd := `select * from productDetailData`
	rows, _ := db.Query(cmd)
	defer rows.Close()
	var pDetials []ProductDetailData
	for rows.Next() {
		var p ProductDetailData
		rows.Scan(&p.ProductDetailDataId, &p.ProductDataId, &p.GrossProfitMargin, &p.PurchaseDate, &p.SalesDate)
		pDetials = append(pDetials, p)
	}
	err := rows.Err()
	if err != nil {
		log.Fatalln(err)
	}
        return pDetials
}

db.Queryでクエリを実行し、取得したrowsをforで回し、各行のデータをrows.Scanでデータを取り出しています。

ここで注目してほしいのは、rows.Scanでデータを取り出しているところです。

rows.Scan(&p.ProductDetailDataId, &p.ProductDataId, &p.GrossProfitMargin, &p.PurchaseDate, &p.SalesDate)

このように、structの各カラムをずらずらと並べる必要があります。例のstructはまだカラムが少ないからいいですが、カラムが多かったり、カラムを増減したりすると、いちいち修正する必要があります。面倒くさいですね。

sqlxで全データを取得してみよう

import "github.com/jmoiron/sqlx"
func getAllProductDetailData () []ProductDetailData {
	db, _ := sqlx.Open("sqlite3", "./sellManagement.sql")
	defer db.Close()
	cmd := `select * from productDetailData`
	rows, _ := db.Queryx(cmd)
	defer rows.Close()
	var pDetials []ProductDetailData
	for rows.Next() {
		var p ProductDetailData
		if err := rows.StructScan(&p); err != nil {
			log.Fatalln(err)
		}
		pDetials = append(details, p)
	}
	err := rows.Err()
	if err != nil {
		log.Fatalln(err)
	}
	return pDetials
}

同じことをsqlxを使ってやってみました。

sqlxの場合はrows.StructScanを使ってデータを取り出しています。sqlと大きな違いはカラムを1つ1つ並べる必要がないところです。いや〜便利ですね。これで、カラムが増減しても、怖くありません。よってsqlxを使うべし

sqlxでIn句を使ってみる

func getProductDetailDataListByIds(ids []int) []ProductDetailData {
	db, _ := sqlx.Open("sqlite3", "./sellManagement.sql")
	defer db.Close()

	query, args, err := sqlx.In(`select * from productDetailData where productDetailDataId in (?)`, ids)
	if err != nil {
		log.Fatalln(err)
	}
	query = db.Rebind(query)
	rows, err := db.Queryx(query, args...)
	if err != nil {
		log.Fatalln(err)
	}
	defer rows.Close()

	var pDetails []ProductDetailData
	for rows.Next() {
		var p ProductDetailData
		if err := rows.StructScan(&p); err != nil {
			log.Fatalln(err)
		}
		pDetails = append(pDetails, p)
	}
	return pDetails
}

In句を使いたい場合はsqlx.Inを使えば、実現可能です。

query, args, err := sqlx.In(`select * from productDetailData where productDetailDataId in (?)`, ids)

上記のようにidsのスライスを引数に渡してあげることで、queryとargsを吐いてくれます。このqueryとargsを使ってrows, err := db.Queryx(query, args…)のようにすれば、該当の行を取り出すことができます。後はforを使って各データをstructの嵌めていくだけ。

sqlxのインストール

go get github.com/jmoiron/sqlx

最後に

簡単にsqlとsqlxの使い方を紹介させていただきました。使い勝手はsqlxのほうが断トツに良いので、GoでDBを扱う時にsqlxを使うべし

より詳しく知りたい場合はドキュメントを御覧ください。

Go言語を勉強するならこれ!

最後にプログラミング基礎の勉強はやはり本は一番だと思いますので、基礎をしっかり学べたい方は是非、一冊を手にとってみてはいかがでしょうか?

合わせて読みたい

コメント

タイトルとURLをコピーしました