CodeIgniter中MySQL大小写敏感需在SQL层显式控制:用BINARY前缀或COLLATE utf8mb4_bin实现区分大小写比较,数据库配置dbcollat仅影响新建表默认校对,不改变已有字段行为。

CodeIgniter 默认使用 MySQL 的默认校对规则(如 utf8mb4_unicode_ci),该规则对字符串比较是大小写不敏感的,所以 WHERE name = 'Admin' 和 WHERE name = 'admin' 会命中同一条记录——这不是 Bug,而是 MySQL 行为本身。如果你需要大小写敏感查询,不能靠改 CodeIgniter 配置“开启敏感模式”,而必须显式控制字段比较方式。
MySQL 层面强制大小写敏感比较
最直接、最可靠的方式是在 SQL 中用 BINARY 或指定校对规则(collation)做临时转换。CodeIgniter 查询构建器支持在 where() 中传入原始 SQL 片段:
- 用
BINARY前缀(推荐):$this->db->where("BINARY username", "Admin");—— 这会让比较按字节进行,区分大小写 - 用
COLLATE指定二进制校对:$this->db->where("username COLLATE utf8mb4_bin", "Admin"); - 注意:不要写成
$this->db->where('username', 'Admin', FALSE),第三个参数FALSE只是禁用自动转义,不改变比较逻辑
查询构建器中避免隐式类型转换导致失效
如果字段是 INT 或 ENUM 类型,但你在 where() 中传入字符串(如 $this->db->where('status', 'active')),MySQL 可能做隐式转换,导致索引失效或大小写行为不可控。此时应:
- 确保 PHP 传入的值类型与字段类型一致:
$this->db->where('status', 1)(若 status 是 TINYINT) - 对字符串字段,确认其定义时已指定大小写敏感校对,例如建表时写:
username VARCHAR(50) COLLATE utf8mb4_bin - 避免在 WHERE 中对字段做函数操作,如
LOWER(username) = 'admin',这会无法使用索引
数据库配置本身不决定查询大小写敏感性
很多人误以为改 database.php 中的 char_set 或 dbcollat 能让所有查询变敏感,这是错的。这两个参数只影响连接初始化时的字符集和默认校对规则,不改变已有字段的定义,也不覆盖 SQL 中的显式比较逻辑。
-
$db['default']['dbcollat'] = 'utf8mb4_bin';仅让新创建的表/字段默认用bin校对,已有表不变 - 已有字段仍沿用建表时的校对规则,
SHOW FULL COLUMNS FROM users;可查具体字段的Collation列 - 若需批量修改,得执行:
ALTER TABLE users MODIFY username VARCHAR(50) COLLATE utf8mb4_bin;
真正起作用的是字段定义 + SQL 表达式组合。别指望框架层“开关”能翻转底层行为;该加 BINARY 就加,该改字段校对就改——否则查出来的数据对不上,连 debug 都找不到源头。

















