CodeIgniter多表关联删除必须用事务确保一致性,按外键依赖顺序先删子表再删主表,支持MySQLi/PDO驱动,可结合原生SQL JOIN删除但需手动包裹事务。

<p>CodeIgniter 中实现多表关联删除,必须用事务确保数据一致性,否则容易出现部分删除、数据不一致的问题。核心思路是:开启事务 → 按依赖顺序逐表删除(先删子表,再删主表)→ 全部成功则提交,任一失败则回滚。</p>
<H3>1. 确保数据库驱动支持事务</H3>
<p>CodeIgniter 3 默认使用 MySQLi 或 PDO,都支持事务。检查配置:<font color="red">application/config/database.php</font> 中 <strong>‘dbdriver’</strong> 应为 <strong>‘mysqli’</strong> 或 <strong>‘pdo’</strong>,且 <strong>‘subdriver’</strong>(如用 PDO)设为 <strong>‘mysql’</strong>。无需额外开启,调用 <strong>$this->db->trans_start()</strong> 即自动启用。</p>
<H3>2. 按外键依赖顺序组织删除逻辑</H3>
<p>例如:订单表(orders)→ 订单商品表(order_items)→ 商品表(products),其中 order_items 依赖 orders 和 products。正确顺序应是:<strong>先删 order_items,再删 orders,最后按需删 products(注意:若 products 被其他表引用,不可直接删)</strong>。避免违反外键约束导致事务中断。</p>
<ul>
<li>查清各表间外键关系(可用 <strong>SHOW CREATE TABLE table_name</strong> 查看)</li>
<li>删除时从“最末端”子表开始(即无其他表依赖它的表)</li>
<li>主表(如 users)通常最后删,或仅在确认无级联依赖时才删</li>
</ul>
<H3>3. 使用事务封装多表删除操作</H3>
<p>在模型或控制器中写法示例(以删除某用户及其关联数据为例):</p>
<pre><code>$this->db->trans_start();
// 1. 删除用户地址(user_addresses)
$this->db->where('user_id', $user_id);
$this->db->delete('user_addresses');
// 2. 删除用户订单(orders)
$this->db->where('user_id', $user_id);
$this->db->delete('orders');
// 3. 删除用户本身(users)
$this->db->where('id', $user_id);
$this->db->delete('users');
$this->db->trans_complete();
if ($this->db->trans_status() === FALSE) {
// 回滚已执行的删除
return FALSE;
} else {
return TRUE;
}</code></pre>
<H3>4. 更安全的做法:用 WHERE 子句 + JOIN 避免多次查询</H3>
<p>对强关联场景(如一对一或确定无残留数据),可考虑用原生 SQL 执行带 JOIN 的 DELETE(MySQL 支持),但 CodeIgniter 查询构造器不直接支持多表 DELETE,需手动写:</p>
<pre><code>$sql = "DELETE u, ua, o
FROM users u
LEFT JOIN user_addresses ua ON ua.user_id = u.id
LEFT JOIN orders o ON o.user_id = u.id
WHERE u.id = ?";
$this->db->query($sql, [$user_id]);</code></pre>
<p>⚠️ 注意:该方式绕过 Active Record,不参与 CI 事务管理,<strong>必须配合 $this->db->trans_start() / trans_complete() 手动包裹</strong>,否则仍存在风险。</p>