mysql允许text字段用distinct但默认只比较前1024字节;postgresql要求text/jsonb支持哈希或排序,json类型直接报错;sql server明确禁止text/ntext/image,须cast为varchar(max)且存在截断风险。

不能直接用于包含大文本字段(如 TEXT、CLOB、JSON)的表,除非数据库明确支持且字段可参与比较操作。
MySQL 8.0+ 中 TEXT 字段能否用 DISTINCT?
MySQL 允许对 TEXT 类型字段使用 DISTINCT,但有硬性限制:TEXT 列必须有前缀索引或被隐式截断参与比较——实际去重行为取决于字段是否在排序/哈希阶段能被完整比较。
- 若字段定义为
TEXT且未指定长度(如TEXT、MEDIUMTEXT),MySQL 默认只比较前 1024 字节(具体值依赖max_sort_length配置) - 超出部分被忽略,导致“看起来不同、实际被合并”的静默错误
- 执行
SELECT DISTINCT content FROM articles可能返回比真实唯一值更少的结果,且无警告 - 想强制全量比较?得先转成
CAST(content AS CHAR(10000)),但会显著拖慢性能并可能 OOM
PostgreSQL 对 TEXT 和 JSONB 的 DISTINCT 行为
PostgreSQL 更严格:所有参与 DISTINCT 的列必须具有 ORDER BY 或 HASH 操作符支持。而原生 TEXT 支持,JSONB 也支持;但 JSON(文本格式)不支持,会报错 ERROR: could not determine which collation to use 或 cannot hash type json。
-
SELECT DISTINCT body FROM posts(body TEXT)→ 正常运行 -
SELECT DISTINCT payload FROM events(payload JSON)→ 直接报错ERROR: could not determine which collation to use -
SELECT DISTINCT payload::jsonb FROM events→ 可行,但要注意jsonb会标准化键顺序、删除重复键、忽略空格,和原始 JSON 文本语义不等价
SQL Server 报错 “text、ntext 和 image 数据类型不可用于 DISTINCT”
这是明确拒绝——SQL Server 2016 起已弃用 TEXT/NTEXT/IMAGE,但若旧表仍含这些类型,DISTINCT 会直接失败,错误信息是:Msg 306, Level 16, State 2, Line X: The text, ntext, and image data types cannot be compared or sorted, except when using IS NULL or LIKE operator.
- 必须先显式转换:
SELECT DISTINCT CAST(note AS VARCHAR(MAX)) FROM logs - 但
VARCHAR(MAX)仍有 2GB 上限,超长内容会被截断,且CAST不可索引,无法加速 - 如果字段含大量重复前缀(如日志开头都是相同模板),
DISTINCT仍可能误判为相同——因为 SQL Server 内部哈希或排序时可能只取前若干 KB
真正麻烦的不是语法通不过,而是它“看似成功却悄悄丢数据”:大文本字段的比较逻辑依赖数据库实现细节,没有跨引擎一致性,也没有显式提示你正在丢失精度。一旦业务依赖这个去重结果做去重统计或下游同步,出问题时很难归因。











