codeigniter 无内置sql调试工具,需用 _compile_select() 查执行前sql(仅qb有效)、last_query() 查执行后sql(需确保查询经ci流程);sql server下易误将结果对象当无sql,应结合 last_query() 与 result_array() 分别查语句和数据。

CodeIgniter 框架本身没有内置的“SQL调试工具”,但提供了两个关键方法:一个在查询执行前看生成的 SQL,一个在执行后看实际发出去的 SQL。用错时机或混淆对象类型,是绝大多数人查不到语句的根本原因。
执行前看 SQL:用 $this->db->_compile_select(),不是 last_query()
这个方法只对 Query Builder(查询构造器)有效,比如链式调用 select()、where()、join() 后还没调用 get() 时使用。它不执行查询,只拼接并返回字符串。
- 必须在
get()、insert()、update()等执行方法调用之前调用,否则返回空或旧结果 - 注意函数名带下划线:
_compile_select()是受保护方法,CI3 允许直接调用,但 CI4 已移除,别写成compile_select() - 如果用了
query($sql)手写 SQL,则此方法无效——你 already have the SQL
示例:
$this->db->select('id, name')->from('users')->where('status', 1);
echo $this->db->_compile_select(); // 输出:SELECT id, name FROM users WHERE status = 1
// 此时还没执行,$this->db->last_query() 仍为上一次查询的结果
执行后看 SQL:用 $this->db->last_query(),但得确保它真被调用了
这个方法返回最近一次由 CI 执行的完整 SQL 字符串(含引号、转义),适用于所有查询方式:Query Builder 或 query($sql)。但它依赖于查询确实走过了 CI 的执行流程。
- 如果数据库连接失败、查询被跳过(如条件未满足)、或用了原生 PDO/SQLSRV 直连绕过 CI 封装,
last_query()就不会更新 - 在模型中调用后立刻 echo,别等视图层再取——中间可能有其他 CI 查询覆盖了它
- CI3 中该方法始终可用;CI4 改为
$this->db->getLastQuery()->getQuery(),且需开启DB_DEBUG = true
常见误操作:
$query = $this->db->query("SELECT * FROM users WHERE id = ?", [$id]);
// ✅ 正确:执行完立刻取
echo $this->db->last_query();
<p>// ❌ 错误:中间穿插了其他查询
$this->db->select('*')->from('logs')->limit(1)->get();
echo $this->db->last_query(); // 输出的是 logs 查询,不是上面那条
</p>
SQL Server(sqlsrv)驱动下查不到结果?先确认你拿到的是结果对象,不是 SQL
很多人调用 $this->db->query($sql) 后直接 var_dump(),看到的是 CI_DB_sqlsrv_result 对象,误以为“没查到”或“SQL 没执行”。其实查询成功了,只是你没从对象里取数据。
-
$this->db->last_query()和result_array()是两件事:前者看语句,后者取数据 - SQL Server 驱动下,
num_rows()可能返回 0 即使查询语法正确——常见于未 set ANSI_NULLS ON 或存储过程没设 SET NOCOUNT OFF - 调试时加一句
if (!$query) { log_message('error', $this->db->error()['message']); }能捕获底层驱动报错
安全做法:
$sql = "SELECT TOP 5 * FROM aplikasi";
$query = $this->db->query($sql);
if (!$query) {
log_message('error', 'SQL failed: ' . $this->db->error()['message']);
} else {
echo "<pre class="brush:php;toolbar:false;">" . htmlspecialchars($this->db->last_query()) . "";
print_r($query->result_array()); // 这才是你要的数据
}
真正容易被忽略的点:SQL 日志和 last_query() 都不记录事务内的语句重试、隐式提交或连接复用导致的语句覆盖。如果查不到预期 SQL,优先检查是否被后续的 get()、trans_start() 或日志中间件冲掉了。











