codeigniter中query builder适用于标准crud与表结构稳定的场景,天然防sql注入;原生sql必用于跨库join、ddl/dml混合操作及存储过程调用;控制器直调$db引发n+1查询和逻辑耦合,须严格收敛至model层。

CodeIgniter数据库操作利弊全解析,聚焦实际开发中模型层与查询构造器的选用矛盾:何时该用Query Builder、何时必须写原生SQL、哪些场景下直接调用$db会导致架构隐患。
Query Builder适合什么场景
当你要执行标准CRUD且表结构稳定时,Query Builder是首选。它自动生成参数化语句,天然防御SQL注入,语法链式调用清晰易读。
比如插入一条用户记录:$this->db->insert('users', ['name' => $name, 'email' => $email]);
更新多字段也只需一行:$this->db->update('users', ['status' => 'active'], ['id' => $id]);
【注意】Query Builder不支持复杂子查询嵌套或窗口函数,强行拼接会导致语法错误或逻辑错位。
原生SQL不可替代的三种情况
方法一:跨库关联查询
CI4默认不支持跨数据库JOIN,必须用$this->db->query("SELECT u.name, p.title FROM users u JOIN posts p ON u.id = p.user_id")显式声明。
方法二:批量数据迁移或初始化
执行TRUNCATE TABLE、INSERT INTO ... SELECT这类DDL/DML混合操作,Query Builder无对应方法,硬套会触发异常。
方法三:调用存储过程或自定义函数
例如$this->db->query("CALL generate_report(?, ?)", [$start_date, $end_date]),参数绑定仍受保护,但语法自由度远超Query Builder。
控制器里直接调用$db的致命风险
第一步:打开任意控制器文件,找到类似$db = \Config\Database::connect();的代码行
第二步:检查该$db实例是否被用于视图渲染前的数据组装
第三步:确认是否存在循环内多次调用$db->query()——这会触发N+1查询问题,单页加载可能发起37次数据库往返
这种写法绕过模型层封装,导致业务逻辑与数据访问耦合。一旦表字段重命名,所有散落在控制器里的SQL都要手动改,漏一处就报错。
【关键前提】所有数据库交互必须收敛到Model类中,控制器只负责调度,视图绝对禁止接触$db对象。
事务处理的正确打开方式
在Model方法内开启事务:$this->db->transStart();
执行多条写操作,如插入订单主表→插入订单明细→扣减库存
最后统一判断:if ($this->db->transComplete()) { return true; } else { return false; }
事务失败时,Query Builder会自动回滚,但原生SQL需确保每条语句都参与同一事务上下文——否则transComplete()无法捕获孤立语句的异常。











