尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

MySQL 1267错误解析:字符集与排序规则冲突的定位与修复

MySQL 1267错误解析:字符集与排序规则冲突的定位与修复 先说个场景。你正跑着一个联表查询或者刚把老库的数据同步到新环境一条SQL“啪”地甩过来ERROR 1267 (HY000): Illegal mix of collations (utf8mb4_general_ci,IMPLICIT) and (utf8mb4_0900_ai_ci,IMPLICIT) for operation 。中文直译就是“非法的排序规则混用”。碰到这个错的人十有八九是第一次认真面对MySQL里的collation概念。这个报错不复杂但它能把一个经验挺足的开发卡住半天因为报错信息里全是没细看过的术语网上答案又东一句西一句照抄了还可能把字段属性改丢。这篇文章我打算把1267从根上拆清楚包括它到底在比什么、怎么在一堆表里快速定位冲突字段、临时和彻底两种修复怎么选以及改完之后会连带哪些“看不见”的影响。无论你是被线上故障逼着查问题还是建表时想把字符集和排序规则一步到位这文都能当参考。1. 认识错误1267到底在说什么1.1 字符集和排序规则两个容易搞混的概念MySQL里有两层东西一个是charset一个是collation。字符集管的是“字符怎么存进字节”比如utf8mb4、gbk、latin1它决定了一个汉字占几个字节、哪些字符能存进去。排序规则管的是“存好之后怎么比较和排序”比如utf8mb4_general_ci、utf8mb4_unicode_ci、utf8mb4_0900_ai_ci。你可以把字符集当成一套编码方案把排序规则当成这套方案下的“比较口径”。同样是utf8mb4这个字符集可以配多个collation它们对大小写、重音、特殊字符的处理方式不一样。举个最简单的例子utf8mb4_bin是按二进制逐字节比较也就是区分大小写的A和a是不同字符串而utf8mb4_general_ci是大小写不敏感的A和a视为相同。同一个字符集下面不同collation意味着数据库对“谁大谁小、谁等于谁”的判定标准完全不同。当两个字符串来自不同的collation体系时MySQL不知道按谁的规则来比较于是干脆拒绝执行这就是1267的根源。很多人会问既然是同一个字符集为什么还不能比这是因为MySQL内部对字符串比较有一套“派生规则”coercibility rules。只有当两个操作数的collation能兼容、或者其中一个可以被另一个覆盖时比较才能进行。如果两边都是隐式获得的collation优先级相同规则又不同MySQL直接抛错避免得出不靠谱的比较结果。这一点理解透了后面所有解决方案就都好理解了。1.2 报错信息拆解IMPLICIT和EXPLICIT分别代表什么实际的报错信息里有两个关键信息一个是collation的名字另一个是它的来源级别。IMPLICIT表示这个排序规则是“隐式”得来的比如直接从表字段、表定义继承过来的。EXPLICIT表示是显式用COLLATE子句强行指定的。还有一种叫COERCIBLE通常指字符串常量比如SQL里直接写的abc。这三个级别在MySQL内部有优先级显式指定的最高隐式其次常量最低。如果两个操作数里有一个是显式指定了collation那么以它为准不会报错。如果两个都是隐式的又恰好不同则有可能报1267。如果你比较的是一个字段和一个字符串常量常量本身没有固定的collation它通常会追随另一个操作数所以这种情况很少报错。报错往往出现在两个字段、两个结果集、或者字段与函数返回值之间进行比较时。所以你在看报错时不要只盯着Illegal mix of collations这行英文更要看括号里两个collation的名字和级别。比如报错里出现utf8mb4_general_ci和utf8mb4_0900_ai_ci说明参与比较的两侧一个来自老版本常见的general_ci规则一个来自MySQL 8.0的默认0900_ai_ci规则。这两者在MySQL看来不是同一套排序逻辑混在一起就会翻车。看到这个信息你其实已经知道大概方向了。1.3 为什么MySQL这么“死板”不符合比较规则就直接拒绝MySQL在比较两个字符串表达式时会计算两个collation的兼容性。它允许某些unicode系列的collation之间互相转换比如utf8mb4_unicode_ci和utf8mb4_unicode_520_ci在特定条件下可以折算。但general_ci、unicode_ci、0900_ai_ci这三套设计思路差异太大MySQL官方从来没有承诺它们之间可以自由混用。为了避免在不确定的规则上做比较MySQL采用“宁可错杀、不可放过”的策略直接抛1267。这个行为和编程语言里的“类型不匹配不能相加”很像。两个数字不同类型可能自动转换但字符串的collation规则不是一个简单的数值没法作弊式地硬转。你要么把一边显式指定成另一边的规则要么把底层的字段定义统一。这也解释了为什么网上有人说“加个COLLATE就好了”有人说“要ALTER TABLE改字段”这两种说法都对只是适用场景不同。后面我会把不同方案分开讲。2. 快速定位冲突源头三步锁定问题字段2.1 第一步从报错信息看懂是“谁跟谁”在比排查1267第一件事不是翻所有表而是看完整报错上下文。如果是应用日志里的报错最好能找到原始SQL。比如报错信息里提到for operation 说明是等值比较出了问题如果是order或union说明是排序或合并时出了问题。知道了操作类型你就能缩小范围判断是WHERE条件里的关联字段还是ORDER BY后面的排序字段或者是UNION分支里的结果集字段。大多数情况下比较发生在JOIN的ON条件里。这时你去查两个关联表的建表语句重点看关联字段的CHARACTER SET和COLLATE。比如你有一个user表的nickname字段是utf8mb4_unicode_ci另一个order表的customer_name字段是utf8mb4_general_ci按这两个字段关联时就会撞出1267。拿到这两张表的定义问题基本就清晰了一半。也有一种情况比较隐蔽报错SQL里没有JOIN只是在WHERE里写了name somebody但name字段本身没问题是应用传给MySQL的会话变量或存储过程参数带了不同collation。这种就要往连接参数、JDBC配置、存储过程定义方向查不能只盯着业务表。2.2 第二步用information_schema批量检查库表字段定位到具体的库之后与其一张表一张表地SHOW CREATE TABLE不如直接用一条SQL把整个库里所有字段的字符集和排序规则全部拉出来。系统库information_schema里的COLUMNS表存了这个信息。我最常用的检查SQL是SELECT TABLE_NAME, COLUMN_NAME, CHARACTER_SET_NAME, COLLATION_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA your_database AND CHARACTER_SET_NAME IS NOT NULL ORDER BY TABLE_NAME, ORDINAL_POSITION;跑完之后重点看COLLATION_NAME这一列有没有混着不同的值。比如同一个库里大多数表是utf8mb4_general_ci突然有几张表是utf8mb4_0900_ai_ci那冲突源基本就在这几张表里。如果库比较大可以在SQL里加一个GROUP BY COLLATION_NAME先做个汇总看看到底有几种排序规则并存。这个信息可比你肉眼翻建表语句高效多了。需要注意CHARACTER_SET_NAME IS NOT NULL这个条件不能省因为数值、日期、二进制字段在COLUMNS表里是没有字符集信息的不加这个条件还容易产生干扰行。2.3 第三步检查连接参数和库级默认值有些1267不是表结构导致的而是当前连接用的默认collation和表字段对不上。你可以用下面几条命令检查会话状态SHOW VARIABLES LIKE character_set_server; SHOW VARIABLES LIKE collation_server; SHOW VARIABLES LIKE character_set_database; SHOW VARIABLES LIKE collation_database;collation_server是MySQL实例级的默认排序规则新建库时如果没显式指定就沿用这个值。collation_database则是你当前所在库的默认值。如果这两项和表中实际字段用的collation不一致某些场景会触发隐式转换进而报1267。比如你用命令行的mysql客户端连库没加--default-character-setutf8mb4默认可能是latin1或其它字符集这时写入和比较字符串就可能出问题。JDBC连接也一样。老版本驱动和新版本驱动对默认字符集的判断不一致可能在同样的库上出现“一个服务正常、另一个报1267”的奇观。排查时如果表结构检查过没问题就把连接串也检查一遍特别是characterEncoding和connectionCollation这两个参数。3. 解法从临时到彻底的五种方案3.1 临时止血查询里加COLLATE指定排序规则如果只是想先让业务恢复不打算马上改表结构最直接的办法是在SQL里给其中一边加COLLATE显式指定排序规则。比如报错说utf8mb4_general_ci和utf8mb4_0900_ai_ci冲突你可以在JOIN条件里这样写SELECT * FROM user u JOIN order_info o ON u.nickname o.customer_name COLLATE utf8mb4_unicode_ci;这里的关键是COLLATE加在哪一侧哪一侧就会变成“显式指定”优先级瞬间压过另一侧的隐式collation。MySQL就不再有选择困难直接按你指定的规则比较。不过在加的时候要看清楚如果COLLATE加在了被驱动表的字段上那侧字段可能没法走普通索引。举个例子u.nickname o.customer_name COLLATE utf8mb4_unicode_cicustomer_name被包装成表达式索引可能失效而u.nickname身上没有函数包裹索引仍然可以用。如果你要保留索引性能尽量把COLLATE加在右表或小表一侧或者说加在“不需要走索引优化”的那一侧具体得看SQL和表的大小。此外还可以用CONVERT()函数转换一边的字符集和排序规则WHERE CONVERT(u.nickname USING utf8mb4) COLLATE utf8mb4_unicode_ci o.customer_name;这种写法适合两边字符集都不同的极端情况。临时方案的好处是不动表结构回滚也容易坏处是每一处有问题的SQL都得改如果这是一个老系统里被几十个模块调用的公共查询你不可能一个个改完。它本质上是止血不是根治。3.2 精确修复ALTER TABLE MODIFY单列如果确认只有某几个字段的collation和其他字段不一致可以直接用ALTER TABLE ... MODIFY修正单列。例如ALTER TABLE order_info MODIFY COLUMN customer_name VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT ;这里一定要强调一个大坑MODIFY COLUMN是整列替换定义不是只改collation。你在SQL里写了哪些属性最终列就只有哪些属性。如果不小心漏掉NOT NULL、DEFAULT、COMMENT等这些属性会被悄悄抹掉。我见过有人改完一个字段默认值没了应用插入数据时直接报错Field customer_name doesnt have a default value。所以实操时先去SHOW CREATE TABLE把原字段完整定义复制过来再在上面加CHARACTER SET和COLLATE而不是凭记忆写。还有一点修改字段的collation时会触发表上的索引重建。如果这是一张大表或者这个字段上有二级索引、唯一索引操作耗时可能远比你想象的长。线上大表建议安排在低峰期或者先用pt-online-schema-change这类工具处理避免长时间锁表拖垮业务。3.3 批量修复ALTER TABLE ... CONVERT TO整表转换如果一张表里多个字符字段都乱了不想一个个改可以用一条语句把整张表的所有字符类型列统一转换ALTER TABLE order_info CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;这个操作会把表中所有CHAR、VARCHAR、TEXT、ENUM、SET等字符类型列全部转成指定字符集和排序规则同时会重写表数据、重建索引。在数据量大的情况下这个操作比单列MODIFY耗时更长而且锁表范围更大。执行之前要评估表的行数和磁盘空间像几千万行的表不建议直接在生产环境跑。批量转换适合什么场景适合那种“整张表的字符集选错了全部要换”的情况。比如早期建表用了utf8实际是utf8mb3现在为了支持emoji要改成utf8mb4这种全局性变更用CONVERT TO就很合适。如果你只是想统一某个列还是用上一节的MODIFY更精准免得把别的字段的排序语义也改了。3.4 根治统一库、连接与SQL脚本中的默认值临时方案和局部修改都解决不了“这个库本来就是乱的”问题。真正要根治是让整条链路从库到表到连接到SQL脚本都使用同一个collation。先看库的默认值ALTER DATABASE your_database CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;注意这个命令只改库的默认值不会自动转换库中已经存在的表。它影响的是之后新建的表如果新建表时不写DEFAULT CHARSET会继承这个库级默认值。连接层面也要统一。JDBC连接串可以显式指定jdbc:mysql://localhost:3306/your_database?useUnicodetruecharacterEncodingutf8connectionCollationutf8mb4_unicode_ci命令行客户端连接时指定mysql --default-character-setutf8mb4 -h 127.0.0.1 -P 3306 -u root -p还有SQL脚本和导入文件。很多人从旧环境导出.sql文件再导入新环境时脚本里会带着DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_0900_ai_ci一类建表语句而目标库里的表是utf8mb4_general_ci导入后两边规则就不一致。这种问题看脚本里的建表语句就能发现处理办法是在导入前统一脚本里的字符集与排序规则或者导入后用前面说的信息查询SQL再巡检一遍。3.5 选型建议到底该统一成哪个collation这是每次处理1267时绕不开的问题既然要统一统一成哪个比较好我的建议是看MySQL版本。如果所有实例都是MySQL 8.0首选utf8mb4_0900_ai_ci这是8.0默认值新版本对Unicode的支持更完善常规业务完全够用。如果实例是5.7、5.6或者混合版本不要选0900_ai_ci老版本根本不认识这个排序规则连字段都建不出来。这时候用utf8mb4_unicode_ci或者utf8mb4_general_ci更稳妥。二者区别在于前者按Unicode规则排序准确度更高后者速度快一点但对某些字符排序不够精确。日常业务两者差别不大。如果对大小写敏感有硬性要求比如账号、用户名、验证码场景可能需要utf8mb4_bin或utf8mb4_0900_bin。但从“避免1267”的角度我不会让一个库同时存在多种_bin和_ci混用的字段否则以后比较起来又是一堆坑。统一不代表“所有字段都必须一模一样”而是参与比较、关联、合并的那些字段要一致。比如user表和order表关联用的nickname和customer_name这两个必须一致至于其他存储型字段比如某张表有个remark用utf8mb4_bin只要不参与冲突比较问题不大。当然为了省心我倾向于让同一张业务表里的字段类型尽量整齐这样后面写SQL时不需要总想着给谁加COLLATE。4. 真实场景复盘那些容易踩的隐含雷区4.1 JOIN连接条件冲突重点看COLLATE加在哪一侧之前提到JOIN是1267最集中的爆发点。有一次我帮同事排查一个报表任务两张表都只有几千行但每次JOIN都报Illegal mix of collations。查出来以后两张表的关联字段一个是utf8mb4_general_ci一个是utf8mb4_unicode_ci。按理说用临时COLLATE能立刻解决但我当时提醒同事注意索引问题如果把COLLATE加在索引列那一侧ON条件里的索引列变成了表达式优化器就没法直接走索引。他不是太信跑了一下执行计划果然type从ref变成了ALL。所以JOIN场景有一个实操原则COLLATE加在非索引侧或者加在“反正没有索引可用”的那一侧。如果是两张小表全表扫描也无所谓如果是大表JOIN索引失效的影响就不是一个报错的问题而是性能灾难。还有一个更稳的办法提前把两个关联字段的底层collation改成一致这样执行计划完全不受影响。4.2 UNION结果集合并两边字段定义不一致UNION也经常触发1267因为MySQL要求合并的列在类型和排序规则上兼容。比如SELECT name FROM user_a UNION SELECT name FROM user_b;如果user_a.name是utf8mb4_unicode_ciuser_b.name是utf8mb4_0900_ai_ci这条SQL基本必报错。处理思路和JOIN类似可以在UNION子句里的某一边加COLLATE显式指定SELECT name COLLATE utf8mb4_unicode_ci FROM user_a UNION SELECT name FROM user_b;如果列多、分支多这种写法的SQL会变得很啰嗦。所以我更建议在遇到UNION冲突时先查两张表的字段定义把不一致的字段统一掉而不是在每一条UNION分支里都塞COLLATE。UNION还有一个特性是最终列名以第一个SELECT为准如果第一列的collation被显式指定了后面的列就会向它对齐这也是为什么在第一个分支加COLLATE往往就能解决整条UNION的原因。4.3 存储过程、视图与临时表的collation“继承”1267不一定发生在普通表之间视图、存储过程、临时表也会参与。视图本质是保存起来的SELECT语句如果视图内部关联的两张表collation不一致查视图时就报错但你在SHOW CREATE VIEW里看到的只是SQL文本需要顺着视图定义里的表名去查字段。存储过程里如果声明了局部变量并显式指定了collation再跟表字段比较同样可能冲突。临时表是另一个容易忽略的点。一个会话里创建的TEMPORARY TABLE如果指定了和业务表不同的collation后续JOIN临时表时就可能报1267。我遇到过一个场景某个存储过程先建临时表存中间结果临时表字段用了utf8mb4_bin再和业务表的utf8mb4_general_ci字段关联时直接报错。后来统一了临时表的collation问题消失。这类问题靠information_schema查不到临时表要直接看存储过程或程序代码里的建表语句。4.4 数据迁移与升级后的1267还有一种比较冤的情况业务代码一行没改原来跑得好好的做了数据迁移或版本升级之后突然开始报1267。原因多半是源库和目标库的默认collation不同。比如从MySQL 5.7迁移到8.05.7默认utf8mb4_general_ci8.0默认utf8mb4_0900_ai_ci。迁移工具建表时如果没有显式指定collation目标表就用了8.0默认而旧库导出脚本里某些列显式写了utf8mb4_general_ci两边混在一起就会出现一堆1267。数据迁移前我建议先把源库所有表的collation列出来导出成一个清单。然后决定目标库统一用哪套规则迁移时通过模板或参数强制指定。不要指望“库默认一致就万事大吉”因为每张表、每个字段在建表时可以单独指定历史表很可能带着旧规则。5. 改完之后的连带影响与预防建议5.1 大小写敏感语义翻转唯一索引可能立刻冲突这是改collation最容易翻车的地方很多人没意识到。假设某张表的username字段原来用utf8mb4_bin区分大小写那么表里可以同时存在Admin和admin两个用户。现在因为统一collation你把字段改成了utf8mb4_general_ci大小写不敏感这时候字段上如果有唯一索引索引重建时MySQL会发现Admin和admin在比较口径下被视为同一个值立刻抛Duplicate entry Admin for key username。你本想修1267结果业务直接写不进去了。反过来也成立。如果把原来大小写不敏感的字段改成_bin以前无法同时存在的Admin和admin现在能并存了这可能导致登录逻辑出问题用户输入小写却能匹配到另一个账号。所以在调整collation之前必须先想清楚这个字段的业务语义尤其是账号、邮箱、订单号这类承载唯一约束的字段。5.2 索引重建与排序顺序变化字段collation一变等于告诉数据库“以后要按新规则排序”。字符串索引的结构本身依附于排序规则所以MySQL在修改字段collation时会重建相关索引。表越大、索引越多重建时间越长。更微妙的是排序结果也会变。比如某个列表页按nickname排序以前用utf8mb4_general_ci中文按拼音大致排改成utf8mb4_0900_ai_ci后可能某些字符的排序位置会变。前端如果没感知用户可能会发现列表顺序跟以前不太一样。大多数情况下这种变化无伤大雅但如果排序结果影响分页、排行榜之类逻辑就要做回归验证。另外还要留意修改collation时如果有其他会话正在执行查询锁等待可能会拖垮线上。大表变更尽量用在线DDL工具或者接受锁表风险在业务低峰窗口做。5.3 5.7与8.0默认排序规则的兼容性很多团队的架构是多版本MySQL共存5.7和8.0都有甚至会做主从或数据同步。这时不要只看业务库还要看同步链路的隐式转换。比如主库是5.7表和字段都是utf8mb4_general_ci从库是8.0某些新表自动使用了utf8mb4_0900_ai_ci。应用在主库上跑一条JOIN没报错但在从库上跑同样SQL可能报1267因为在从库上逻辑一样的字段带着不同的collation。这种问题在排查时容易跑偏因为你可能反复验证主库SQL没问题却没意识到从库执行环境不一样。如果要在多版本环境长期共存我建议所有实例都显式设置一个共同的默认值比如统一的utf8mb4_unicode_ci。这样不管跑在哪个版本上只要字段定义时没有显式覆盖新表默认都一致。5.4 预防性巡检SQL模板不要每次都等报错才去查完全可以写个一次性巡检脚本定期跑。下面这个SQL专治“一个库里存在多种排序规则”的情况SELECT TABLE_NAME, COLLATION_NAME, COUNT(*) AS column_count FROM information_schema.COLUMNS WHERE TABLE_SCHEMA your_database AND CHARACTER_SET_NAME IS NOT NULL GROUP BY TABLE_NAME, COLLATION_NAME HAVING COUNT(*) 0 ORDER BY TABLE_NAME;每组结果里你只需要关心那些“同表出现多个COLLATION_NAME”的小组或者“同库COLLATION_NAME分布特别零散”的情况。如果整个库绝大多数表都是utf8mb4_unicode_ci只有个别表冒出来一个utf8mb4_general_ci那基本能定为隐患。我也习惯把这个巡检SQL放到运维平台的定时任务里每周自动出一份报告总比在故障时抢救要省心。6. 高频问题速查与个人踩坑记录6.1 高频问题速查表报错或现象常见原因快速解法JOIN时报1267两个关联字段collation不同临时COLLATE一侧或ALTER TABLE MODIFY统一字段UNION时报1267两边结果集字段排序规则不一致在第一个分支加COLLATE或统一底层字段导入SQL后新表报1267SQL脚本里建表语句的collation与库默认不同统一脚本中的DEFAULT CHARSET和COLLATE升级驱动后开始报1267新旧驱动默认collation不同JDBC连接串显式指定connectionCollation存储过程里报1267局部变量或临时表collation与表字段不一致在变量定义、临时表建表语句中显式指定collation大表改完collation后变慢索引重建、锁表低峰期操作或用在线DDL工具改完collation后插入报主键冲突大小写敏感性改变唯一索引判定变化先清重或改用与业务语义匹配的collation这张表覆盖了绝大多数1267的实际场景。遇到问题先不要急着搜“怎么强制忽略报错”因为collation是数据库判断数据相等性的依据忽略它只会得到错误结果。6.2 三个真实排查记录先说第一个。今年年初一个Java服务从MySQL 5.6迁移到8.0迁移后用了一段时间某张报表的汇总查询开始报1267。我看了代码SQL里关联了三四张表其中两张表是迁移工具从5.6原样重建的字段是utf8mb4_general_ci另一张表是DBA手工程序建在8.0上的字段自动用了utf8mb4_0900_ai_ci。三种规则混在一起只要JOIN就炸。最后处理方式不是逐条SQL加COLLATE而是把新手动建的那张表统一成utf8mb4_general_ci问题彻底消失。第二个是关于驱动的。同事反馈“同一个库、同一个用户、同一张表服务A正常服务B报1267”。我先查表结构完全没问题查连接参数才发现服务A用的JDBC驱动是5.x连接串里带了characterEncodingutf8但没带connectionCollation驱动默认用了老规则服务B用的JDBC驱动是8.0.x默认按utf8mb4_0900_ai_ci建会话。两者连同一批表表里既有老字段又有新字段于是有的SQL在服务A正常在服务B报错。给两个服务都显式指定connectionCollation之后行为完全一致了。第三个是视图里的坑。一个视图嵌套了三层子查询每层都从不同表取字段最外层做GROUP BY时报1267。单独看每张表的字段都是utf8mb4但有的表是utf8mb4_general_ci有的是utf8mb4_bin。视图把这几套规则串在一起到了聚合比较时MySQL受不了了。因为修改底层表影响面大我先在视图最外层的列上加COLLATE统一收口先让业务恢复同时列出排查报告推动后续统一表字段。6.3 我的一些习惯踩过几次坑之后我处理1267养成了一些固定习惯。首先库里所有新表建表时都显式写DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci不依赖库级默认值。这样即使数据库迁移或实例配置变化表结构也不受牵连。其次每次上线前跑一次巡检SQL把不同collation的字段都扫出来该统一的提前统一而不是等上线后报错再救火。最后所有参与JOIN、UNION、GROUP BY的公共字段我都建议在表设计评审阶段就把字符集和排序规则对齐。如果你手头已经有一堆乱了的表我的建议是别追求一步到位全改完那样动静太大。可以先按业务影响排序先把参与高频查询、关联查询的字段统一再逐步处理其余低风险字段。1267这个问题本质上不复杂难的是“为什么这么多人会被它绊住”。说白了在MySQL的世界里数据存储除了类型之外还有一套字符比较规则这套规则平时藏得很深你只有碰到冲突报错时才会注意到它。我个人最深的体会是不要在报错现场硬记COLLATE的写法而是花十分钟把它的机理搞清楚。因为1267不会只出现一次这个解决了下一个类似的报错可能换一种形式又出现。理解了排序规则和隐式派生的关系很多看起来莫名其妙的MySQL报错在你眼里就是“两边规则不同手动定一个就行”这么简单。
返回列表