最常见查询错误是字段名拼错(如user_name写成username)或类型不匹配(如INT字段误用like);CI3中where()多参数会被静默丢弃,须拆分为多个链式调用。

查询条件拼错或类型不匹配最常见
比如 where('user_name', $name) 写成 where('username', $name),字段名少个下划线;或者对 INT 类型的 phone 字段用 like(),MySQL 拒绝隐式转字符串,但 CI3 默认不报错,只返回空结果。
检查方法:打开 $db['default']['save_queries'] = TRUE,然后在控制器末尾加 var_dump($this->db->last_query());,把生成的 SQL 拿到数据库里手动执行,看是否真没数据、还是语法/字段出问题。
- 确认字段名和表结构完全一致(大小写、下划线、前缀)
- 数值字段别用
like(),改用where()或显式CAST(phone AS VARCHAR) - 日期字段确保传入格式是
'Y-m-d',如'2025-06-01',不是时间戳或数组
CI3 的 where() 多参数被静默丢弃
这是高发陷阱:->where('category_ID', $caid, 'sold_date >=', $start) 这种写法,CI3 只认前两个参数,后面全忽略——结果查出一堆跨年乱数据,你以为“有结果”,其实根本没走日期过滤。
正确必须拆开写:
$this->db->where('category_ID', $caid)
->where('sold_date >=', $start)
->where('sold_date <=', $end);
- CI3 的
where()不支持复合条件单次调用,文档也没明说,容易踩 - 如果条件动态多变,用数组形式:
->where(['category_ID' => $caid, 'status' => 'active']) - 字符串条件(如
'sold_date BETWEEN ? AND ?')要配query()才安全,get()不支持原生 SQL 片段
查不到就直接 row()->xxx 导致 PHP 致命错误
$result = $query->row()->sold_price 看似简洁,但只要没匹配行,row() 返回 null,再取属性就崩: Trying to get property 'sold_price' of non-object。这不是“结果为空”,是直接中断脚本。
必须先判空:
$result = $query->row(); $sold_price = ($result && isset($result->sold_price)) ? (float)$result->sold_price : 0.0;
- 永远不要链式调用
row()后立刻访问属性 - 用
num_rows()判断是否有结果比判row() === null更直觉 - 聚合函数如
select_sum()即使无记录也返回 0,但字段名仍要防空对象
SQLSRV 驱动下结果对象行为不一致
用 SQL Server 时,result() 和 result_array() 返回结构可能和 MySQL 不同:比如空结果时前者返回空数组,后者返回 false;或者字段名全大写、带表前缀,导致 $row->id 访问失败。
对策是统一用 result_array() + 键名检查:
$rows = $query->result_array(); $id = !empty($rows) ? (int)$rows[0]['id'] : 0;
- SQLSRV 驱动需确认
char_set设为utf8,否则中文字段可能乱码变空 - 避免依赖对象属性访问,数组方式更稳,尤其跨数据库迁移时
- 连接配置里
db_debug开发期必须开,不然 SQLSRV 错误常被吞掉
where() 条件没生效或字段名错位,而不是数据真不存在。先看 last_query() 输出,再盯住那几个易错点,比反复改逻辑快得多。


















