Database 手册 · Chapter 6
SELECT 模式
读取 SQL 归纳为两种流程。
| 模式 | API | 用途 |
|---|---|---|
| A) 单值 | RunSqlScalarInt(sql) 等 | COUNT(*) 这样单格结果 |
| 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 : 按列顺序返回一行的 XArray
// 一条 CSV 行(用逗号拼接)= DataGrid 一行
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 行加入
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 < ?"
// → 第二个参数传 [from, to] 数组给 RunSqlSelect参数化 SELECT
RunSqlSelect 同样可以在第二参数接收参数数组 — 与 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 就会自动刷新。该绑定是下一章的主题。