You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MariaDB主键相似字符唯一性冲突问题及PostgreSQL行为咨询

这个问题我之前在开发Django项目时碰到过好几次,核心就是数据库的**排序规则(Collation)**在搞怪!

为什么会出现主键冲突?

MariaDB/MySQL默认用的排序规则(比如utf8_general_ci、utf8mb4_general_ci)是重音不敏感的——这类规则会把带重音的字符(像ó、é)和对应的无重音字符(o、e)当成完全一样的内容。所以当你插入主键值分别为ó和o的两行时,数据库会判定主键重复,直接抛出1062错误。

而SQLite没这个问题,是因为它默认对字符串用二进制比较,直接看字符的二进制编码是否相同,ó和o的编码不一样,自然不会被视为重复。

解决方法:修改排序规则为"重音敏感"

要让数据库区分这些带重音的字符,你需要把表或者主键列的排序规则改成重音敏感的,这里有两个靠谱的方案:

方案1:二进制排序规则(简单直接)

二进制排序规则会严格按字符的二进制编码来比对,完全区分所有不同字符(包括重音、大小写)。执行下面的SQL就能修改整个表的设置:

-- 先把字符集改成utf8mb4(推荐,支持所有Unicode字符),再设置二进制排序规则
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;

如果你只想改主键列的规则,单独修改即可:

ALTER TABLE table_name MODIFY term VARCHAR(64) NOT NULL PRIMARY KEY COLLATE utf8mb4_bin;

方案2:Unicode标准排序规则(排序更合理)

如果你希望字符排序符合Unicode标准,同时区分重音,可以用utf8mb4_0900_as_cs(适用于MySQL 8.0+、MariaDB 10.5+)。这个规则不仅区分重音,还区分大小写,而且排序逻辑比二进制更人性化(不会单纯按编码值排序):

ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_as_cs;

小提醒:修改排序规则前最好备份一下数据,避免意外;新项目建议一开始就配置好正确的字符集和排序规则,省得后期折腾。

关于PostgreSQL的情况

默认情况下,PostgreSQL不会出现这个问题。

PostgreSQL的字符串比较默认依赖数据库的collation,大多数默认的collation(比如en_US.utf8)都是区分重音的,'ó'和'o'会被判定为不同的值。只有当你特意用了忽略重音的collation(比如en_US.utf8@accent=ignore),或者手动用unaccent()函数处理字符串后再比较,才会把它们当成一样的。

内容的提问来源于stack exchange,提问作者beruic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:10:07