C# 使用OleDbDataReader执行SQL查询数据库仅返回1问题排查
问题根因
- 变量使用错误:
Double.TryParse的返回值renew是布尔类型,仅代表字符串转数字是否成功,你错误地将该布尔值拼接到了SQL比较条件中。布尔值在SQL执行时会被转为数值1/0,所以无论输入的实测值是多少,查询条件永远是Mass >= 1或者Mass >= 0,这是输出始终为1的核心原因,正确应该使用转换后的数值变量dNumber。 - 表名拼写错误:第二条查询SQL中的表名写为
Tabels,和第一条的Tables不一致,若实际表名为Tables会直接导致查询结果异常。 - 逻辑完全冗余:第一条排序查询没有任何实际作用,外层循环遍历所有排序后的记录,每次都执行相同的比较查询,最终
lblUpperValue只会被最后一次循环的结果覆盖,属于无效逻辑。
排查方向
- 打印输出
SqlCmdCompare的实际拼接结果,可直接发现变量用错、表名拼写错误的问题 - 将拼接后的SQL放到数据库管理工具中直接执行,确认返回结果是否符合预期,先排除SQL本身的问题再排查代码逻辑
- 新增返回值判断,检查
compare.Read()的返回结果是否为true,确认查询是否真的命中了数据 - 核对数据库表名、
Mass列的拼写是否和SQL语句中一致
优化建议
- 合并两条SQL为单条查询,直接执行
SELECT TOP 1 Mass FROM Tables WHERE Mass >= ? ORDER BY Mass ASC,一次查询即可拿到第一个大于等于实测值的记录,无需多次查询加循环 - 必须使用参数化查询,禁止直接拼接SQL字符串,既可以避免SQL注入风险,也能解决不同地区数值格式的兼容性问题
- 新增输入合法性校验,当
Double.TryParse返回false时给用户对应提示,不要执行后续无效查询 - 所有实现了
IDisposable接口的对象(OleDbCommand、OleDbDataReader)都用using语句包裹,自动释放资源,不需要手动调用Close方法 - 读取数据时指定列名而非索引,例如
compare["Mass"].ToString(),避免表结构变动后索引错位的问题 - 无需手动关闭OleDbConnection,外层的
using语句会在代码块执行结束后自动关闭连接
修正后的参考代码
string conn = TableSettings.Instance.GetConnectionString(); string readingInDoubles = lblReading.Text; // 校验输入合法性 if (!Double.TryParse(readingInDoubles, out double dNumber)) { lblUpperValue.Text = "输入格式错误"; return; } // 合并后的SQL,OleDb参数用?占位 string sqlCmd = "SELECT TOP 1 Mass FROM Tables WHERE Mass >= ? ORDER BY Mass ASC"; using (OleDbConnection connect = new OleDbConnection(conn)) using (OleDbCommand command = new OleDbCommand(sqlCmd, connect)) { // 添加参数,OleDb按参数添加顺序匹配占位符 command.Parameters.AddWithValue("@Mass", dNumber); connect.Open(); using (OleDbDataReader reader = command.ExecuteReader()) { if (reader.Read()) { lblUpperValue.Text = reader["Mass"].ToString(); } else { lblUpperValue.Text = "无匹配记录"; } } }
内容的提问来源于stack exchange,提问作者LoonieToonie
相关产品推荐
相关产品推荐

