CodeIgniter 多条件组合删除需确保各条件真实参与逻辑判断,避免漏删误删;用 Query Builder 链式 where、or_where、group_start 清晰表达“且”“或”及括号优先级。

CodeIgniter 中实现多条件组合删除,关键不是堆砌 WHERE 条件,而是让每个条件都真正参与逻辑判断,避免漏删、误删或 SQL 报错。Query Builder 提供了链式 where 方法,配合 or_where、group_start 等,能清晰表达“且”“或”“括号优先级”等真实业务逻辑。
基础多条件 AND 删除(全部满足才删)
适用于如“删除状态为已归档、创建时间早于2025年、且类型为临时的记录”这类严格并列条件:
- 使用连续 $this->db->where() 即可自动拼接 AND
- 数值、字符串会自动转义,无需手动处理单引号
- 示例:
$this->db->where('status', 'archived')
->where('created_at <', '2025-01-01')
->where_in('type', ['temp', 'draft'])
->delete('articles');
生成的 SQL 等效于:
DELETE FROM articles WHERE status = 'archived' AND created_at
含 OR 的混合条件(需括号分组)
当逻辑变成“(状态=已归档 或 类型=测试)且 创建时间早于2025年”,就必须用 group_start() / group_end() 明确作用域,否则 OR 会破坏整体 AND 结构:
- group_start() 相当于左括号 (,group_end() 是右括号 )
- 不加 group 会导致 OR 优先级混乱,可能删掉不该删的行
- 示例:
$this->db->group_start()
->where('status', 'archived')
->or_where('type', 'test')
->group_end()
->where('created_at <', '2025-01-01')
->delete('articles');
生成的 SQL 等效于:
DELETE FROM articles WHERE (status = 'archived' OR type = 'test') AND created_at
安全过滤 + 非空校验(防止空条件误删全表)
从用户输入(如表单、URL 参数)接收条件时,必须先验证是否有效,否则 where('id', $id) 中 $id 为空会导致 DELETE WHERE id = '' —— 在某些配置下可能误删整张表:
- 对关键字段做非空和类型检查,比如 ID 应为正整数
- 用 where_in() 替代多个 or_where,更简洁且防注入
- 建议搭配事务(trans_start/trans_complete)确保原子性
- 示例(带校验):
$ids = $this->input->post('ids');
if (!empty($ids) && is_array($ids)) {
$ids = array_map('intval', $ids); // 强制转整型
$ids = array_filter($ids, function($v) { return $v > 0; });
if (!empty($ids)) {
$this->db->trans_start();
$this->db->where_in('id', $ids)
->where('status !=', 'locked') // 排除锁定项
->delete('items');
$this->db->trans_complete();
}
}
结合 NOT 和范围条件的精准剔除
NOT 条件常用于排除类操作,比如“删除所有非中文、非英文的内容翻译”或“删除价格不在合理区间内的商品”:
- 用 where_not_in() 替代多个 NOT =,语义清晰且高效
- BETWEEN 支持闭区间,适合价格、时间、评分等连续值过滤
- 注意 NULL 值需单独用 is_null() 或 is_not_null()
- 示例:
$this->db->where_not_in('lang_code', ['zh', 'en', 'ja'])
->where('updated_at BETWEEN', "'2024-01-01' AND '2026-01-01'")
->where('title IS NOT NULL')
->delete('content_translations');
生成的 SQL 包含:
lang_code NOT IN ('zh','en','ja') AND updated_at BETWEEN '2024-01-01' AND '2026-01-01' AND title IS NOT NULL

















