查不到数据主因是get()未指定表名或漏写from();get()不执行sql而仅拼接,需调用result()等方法取值;字符集不匹配会导致insert_batch()乱码;所有异常均源于“延迟执行”与“无状态拼接”设计逻辑。

查不到数据?八成是 get() 没指定表名,或者漏了 from() —— 这不是 bug,是 CI 3 查询构建器的设计逻辑。
为什么 $this->db->get() 总是返回空结果?
CI 3 的查询构建器不执行“链式即触发”,select()、where()、order_by() 都只是拼条件,真正发 SQL 的是 get()。但它默认查的是 NULL 表,生成的 SQL 是 SELECT * FROM `NULL`,数据库直接忽略,不报错也不提示。
- 正确写法只有两种:
$this->db->from('users')->get()或$this->db->get('users') -
get()返回的是CI_DB_result对象,不是数组,必须调用result()、row()或result_array()才能取值 - 调试时想看 SQL 字符串?用
get_compiled_select('users'),它不执行,只生成语句
where() 数组 vs 字符串参数怎么选?
数组形式自动转义,安全但能力有限;字符串形式不转义,灵活但危险。选错会导致 SQL 注入或语法错误。
- 安全场景(推荐):
$this->db->where(['status' => 'active', 'deleted' => 0])→ 自动加引号、转义单双引号和特殊字符 - 必须用字符串的场景:字段间比较、函数调用,比如
$this->db->where('created_at > updated_at'),否则写成数组会变成`created_at` = 'updated_at' - 混合条件别硬套
or_where(),容易逻辑错乱;改用group_start()/group_end()显式包括,例如:$this->db->group_start()->where('a', 1)->or_where('b', 2)->group_end()
limit() 和 offset() 顺序为什么影响结果?
CI 3 拼 SQL 完全按方法调用顺序来,而 MySQL 5.7 及之前只认 LIMIT offset, count 语法,不是标准的 LIMIT count OFFSET offset。
-
limit(10)->offset(20)在旧 MySQL 上实际执行的是LIMIT 20, 10(跳过 20 条取 10 条),但你本意可能是跳过 20 条后取前 10 条——这就不对了 - 最稳妥写法:
limit(10, 20),第二个参数就是 offset,CI 内部会按目标方言适配 -
offset()单独调用必须在limit()之后,否则被忽略;分页统计别用count_all_results(),它会清掉已设的where,要用count_all_results(FALSE)
insert_batch() 插入中文失败或乱码?
问题不在构建器,而在数据库连接层字符集没对齐。哪怕表字段是 utf8mb4,只要连接用的是 latin1,整条批量插入 SQL 就会被当拉丁文解析。
- 检查
application/config/database.php中的'char_set' => 'utf8'和'dbcollat' => 'utf8_general_ci',CI 3 不支持utf8mb4直接配置,需手动在mysqli连接后执行SET NAMES utf8mb4 - 更可靠的做法:在
database.php的'dbdriver' => 'mysqli'下加'charset' => 'utf8mb4'(部分 CI 3.1.11+ 补丁支持),并确保 MySQL 服务端已启用utf8mb4 -
insert_batch()本质是拼一条INSERT INTO ... VALUES (),(),(),所以单条出错会导致整批失败,建议先用validate()或array_filter()清理空/非法值
CI 3 查询构建器的“延迟执行”和“无状态拼接”是它最易踩坑的两个底层逻辑,所有看似奇怪的行为——空结果、条件丢失、limit 错位、乱码——几乎都源于对这两点的误判。写完一句,先问自己:SQL 真发出去了吗?表名和字符集真对上了吗?










