Database マニュアル · Chapter 6

SELECT パターン

読み取り SQL は 2 つの流れに整理できます。

パターンAPI用途
A) 単一値RunSqlScalarInt(sql) ほかCOUNT(*) のような 1 セル結果
B) 一括 SELECTRunSqlSelect(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 ステップ

  1. RunSqlSelect(sql) — 結果をメモリにキャッシュ。false で失敗。
  2. RowCount — キャッシュされた結果の行数。
  3. GetRowArray(i)i 番目の行をカラム順の array で。
  4. 結果変換 — ここでは 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 が自動更新されるバインディングが次章のテーマです。