Go 言語(以下 Golang)の database/sql 標準パッケージと、SQLite3 ドライバで DB を作成したものの、動的に作成されたテーブルのため、作成されたテーブル名の一覧を取得する必要がある。
しかも、何件登録されているか、DB 内の総レコード数を後からでも確認する方法がないものか。
Go 1.18 以降、ドライバーは、もちろん天下の mattn さんの "go-sqlite3"。
「"golang" "sqlite3" テーブル名 一覧 取得」でググっても、SQLite コマンドの .table
で確認する方法しか出てこなかったり、「"golang" "sqlite3" 総レコード数」でググっても、データベース内の全件のレコード数が欲しいのに COUNT()
を使った特定のテーブルのレコード数しか情報がなかったので、自分のググラビリティとして。
TL; DR (今北産業)
- SQLite3 では
count()
を呼び出すたびにテーブルのフルスキャンを行うため遅いです。 - SQLite3 は仕様によりテーブルのレコード数を保持していません。キャッシュもしません。
- そのため、レコード数を保持するカウント用のテーブルを作成し更新するのが現実的です。
- 更新するパターン
- すべてのレコードを挿入し終わった後に、カウントテーブルを更新する。
-
INSERT
DELETE
にトリガーを設定しておき、随時カウントテーブルを増減更新する。(全体のパフォーマンスに影響がでます)
- 更新方法
-
WHERE type='table'
でテーブル名一覧を取得する。 - 各々のテーブルで
SELECT count()
によりレコード数を取得する。
-
- 更新するパターン
- 参考文献: 【Golang】SQLite3 の DB で総レコード数をコードから取得したい | Q&A @ Qiita
TS; DR (サンプル)
-
テーブル名一覧を取得し、各々のレコード数を取得する SQL クエリ (for SQLite3)
テーブル名一覧を取得するSQLクエリSELECT name FROM sqlite_master WHERE type = 'table';
各々のテーブルのレコード数を取得するSQLクエリSELECT 'SELECT count(*), "' || name || '" FROM ' || name || ';' FROM sqlite_master WHERE type = 'table';
-
Golang でテーブル名一覧を取得するサンプル。
// GetTable は db のテーブル名一覧を文字列のスライスで返します。 func GetTable(db *sql.DB) ([]string, error){ result := []string{} q := `SELECT name FROM sqlite_master WHERE type = 'table';` res, err := db.Query(q) if err != nil { return nil, errors.Wrap(err, "failed to query database") } var table string for res.Next() { if err := res.Scan(&table); err != nil { return nil, errors.Wrap(err, "failed to scan table name") } result = append(result, table) } sort.Slice(result, func(i, j int) bool { return result[i] < result[j] }) return result, nil }
-
Golang でデータベース内(全テーブル)の総レコード数を取得するサンプル。
func GetTotalRecords(db *sql.DB) int { talbes, err := Tables(db) if err != nil { return -1 } const queryTPL = `SELECT COUNT(*) FROM %s;` result := int(0) for _, table := range talbes { queryTMP := fmt.Sprintf(queryTPL, table) // ここはPrepareでステートメント化した方が速い res, err := k.db.Query(queryTMP) if err != nil { return -1 } if res.Next() { var count int res.Scan(&count) result += count } } return result }