Database マニュアル · Chapter 6
SELECT パターン
読み取り SQL は 2 つの流れに整理できます。
| パターン | API | 用途 |
|---|---|---|
| A) 単一値 | RunSqlScalarInt(sql) ほか | COUNT(*) のような 1 セル結果 |
| B) 一括 SELECT | RunSqlSelect(sql) + RowCount + GetRowArray(i) / GetValue(i, col) | DataGrid 充填、複数行処理 |
サンプルプロジェクトは両方を使います。
パターン A — 単一値取得
DB_Open() の空テーブル判定が代表例です。
int rowCnt = DB["local"].RunSqlScalarInt("SELECT COUNT(*) FROM order_history");
if( rowCnt == 0 )
{
DB_InsertInitialSamples();
}型ごとの関数:
| 関数 | 戻り値型 |
|---|---|
RunSqlScalarInt(sql) | int |
RunSqlScalarDouble(sql) | double |
RunSqlScalar(sql) | string(汎用) |
クエリ結果が空なら 0 / 0.0 / "" を返します。失敗判定は LastError で。
パターン B — 一括 SELECT(DB_Refresh)
サンプルの DB_Refresh() が標準的な流れを示しています。
FUNCTION DB_Refresh()
{
if( DB["local"].IsOpen == false )
{
LogError($"DB_Refresh : DB is not open");
return false;
}
string sql = "SELECT id, order_no, menu_name, start_time, end_time, weight_g, result, is_error FROM order_history ORDER BY id ASC";
if( DB["local"].RunSqlSelect(sql) == false )
{
LogError($"DB_Refresh select failed : {DB["local"].LastError}");
return false;
}
DispData.Clear();
int rows = DB["local"].RowCount;
for( i, 0, rows-1 )
{
// GetRowArray : 1 行をカラム順の XArray で返す
// CSV 1 行(カンマ結合)= DataGrid 1 行
array row = DB["local"].GetRowArray(/*row*/i);
string line = $"{row[0]},{row[1]},{row[2]},{row[3]},{row[4]},{row[5]},{row[6]},{row[7]}";
DispData.Add(line);
}
Log($"DB_Refresh : {rows} rows loaded");
return true;
}4 ステップ
RunSqlSelect(sql)— 結果をメモリにキャッシュ。falseで失敗。RowCount— キャッシュされた結果の行数。GetRowArray(i)—i番目の行をカラム順のarrayで。- 結果変換 — ここでは CSV 1 行にまとめて
DispData配列に追加。
結果キャッシュは次の SELECT が走るか接続が閉じるまで有効です。
セル単位アクセス
行ではなくセル単位で読みたい場合:
DB["local"].RunSqlSelect("SELECT id, menu_name, weight_g FROM order_history WHERE id=?", p);
int id = DB["local"].GetValueInt(/*row*/0, /*colName*/"id");
string menu = DB["local"].GetValue(/*row*/0, /*colName*/"menu_name");
double w = DB["local"].GetValueDouble(/*row*/0, /*colName*/"weight_g");サンプルの DB_OpenModifyDlg(第 7 章)はこのパターンで選択行の全カラムを編集フィールド(Edit*)にコピーしています。
| 関数 | 意味 |
|---|---|
GetValue(row, col) | 文字列(汎用) |
GetValueInt(row, col) | 整数 |
GetValueDouble(row, col) | 実数 |
GetValueBool(row, col) | 真偽 |
row は 0 始まりのインデックス、col はカラム名またはインデックスどちらも可(名前推奨 — カラム順が変わっても安全)。
よく使う SELECT
サンプルドメイン基準 — そのままコピペで試せます:
// 1) 直近 50 件(DataGrid 表示用)
"SELECT id, order_no, menu_name, end_time, result " +
"FROM order_history ORDER BY id DESC LIMIT 50"
// 2) 結果別集計
"SELECT result, COUNT(*) FROM order_history GROUP BY result"
// 3) エラーのみ
"SELECT id, order_no, menu_name FROM order_history WHERE is_error = 1"
// 4) 時間範囲
"SELECT id, order_no FROM order_history " +
"WHERE start_time >= ? AND start_time < ?"
// → RunSqlSelect の第 2 引数に [from, to] 配列を渡すパラメータ付き SELECT
RunSqlSelect も第 2 引数にパラメータ配列を取ります — INSERT/UPDATE と同じパターン。
array p[] = {""};
p.Clear();
p.Add(targetId);
DB["local"].RunSqlSelect("SELECT * FROM order_history WHERE id=?", p);
if( DB["local"].RowCount == 1 )
{
string menu = DB["local"].GetValue(0, "menu_name");
// ...
}よく踏む落とし穴
RowCountは SELECT 直後にだけ意味がある — INSERT / UPDATE 後は再度 SELECT を実行しないと正しい行数は取れません。サンプルは全更新関数の終わりでDB_Refresh()を呼んでこの問題を自動的に回避しています。- SELECT のカラム名は明示する —
SELECT *は環境によりカラム順が変わることがあり、GetRowArrayのインデックス参照が危険になります。 - 空結果 —
RowCount == 0のときにGetValue(0, ...)は空文字列を返しますが、論理上は無意味な呼び出しなので必ずガードしてください。
次の章へ
読み書きコードが揃ったら、次はデータを画面に出す番です — DispData 配列ひとつを更新するだけで XDataGrid が自動更新されるバインディングが次章のテーマです。