Mysql

关注公众号 jb51net

关闭
首页 > 数据库 > Mysql > MySQL collation 差异

详解MySQL collation 差异导致的类型比较行为不同

作者:宁小法先森︿( ̄︶ ̄)︿

MySQL数据库查询差异源于collation排序规则不同,本文就来详细的介绍一下MySQL collation 差异导致的类型比较行为不同,感兴趣的可以了解一下

当参数code为int时查询不到 为string时可查询到

CREATE TABLE `users_amoe_record` (
  `id` int NOT NULL AUTO_INCREMENT,
  `user_id` int NOT NULL DEFAULT '0',
  `key` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
  `code` char(12) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
  `status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0 初始化;1已创建;3 成功收到来信 4收到但过期 5收到但异常',
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `user_id` (`user_id`,`code`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=37494 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

但是另外数据库的数据表, code为int也可以查询到

CREATE TABLE `users_amoe_record` (
  `id` int NOT NULL AUTO_INCREMENT,
  `user_id` int NOT NULL DEFAULT '0',
  `key` varchar(255) NOT NULL DEFAULT '',
  `code` char(12) NOT NULL DEFAULT '',
  `status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0 初始化;1已创建;3 成功收到来信 4收到但过期 5收到但异常',
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `user_id` (`user_id`,`code`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=460090 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

MySQL collation 差异导致的类型比较行为不同

根本原因

两个库的区别:

问题库正常库
code 列 collationutf8mb4_general_ciutf8mb4_0900_ai_ci
MySQL 版本通常 5.7 或早期 8.0MySQL 8.0+ 默认

当 PHP 通过 PDO 绑定整数参数时:

本质是:PDO 发送整数类型参数 + CHAR 字符列 + general_ci 排序规则 = MySQL 类型推导错误。

修复方案

callback() 里对 $code 强转为字符串,让 PDO 以字符串参数发送,与 CHAR(12) 列类型一致:

Read AmoeService.php (lines 120-129)Edit AmoeService.php

Modified

同理,getCaptcha 里查记录时也用了整数查询,也应该修:

Read AmoeService.php (lines 70-77)

getCaptcha 的查询已经有 (string) 强转,不需要改。只需要修 callback 的这一处。

总结

说明
根因utf8mb4_general_ci 排序规则下,PDO 整数参数无法匹配 CHAR(12) 列
为什么另一库没问题utf8mb4_0900_ai_ci(MySQL 8.0 默认)正确处理了混合类型比较
修复$code = (string)$params["code"] — PDO 以字符串传参,与列类型一致
诊断日志确认问题后可以清理掉 ioLog("1") 等调试打点

到此这篇关于详解MySQL collation 差异导致的类型比较行为不同的文章就介绍到这了,更多相关MySQL collation 差异内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文