# 42P21 — 排序规则不匹配

> PostgreSQL SQLSTATE 42P21：来源与诊断参考。
---

# 42P21 — 排序规则不匹配

## 速览 {#at-a-glance}

`42P21`（**collation_mismatch**）需要得到兼容结果时，不同排序规则选择可能发生冲突。

<!-- BEGIN SQLSTATE FACTS: generated by scripts/generate.py; do not edit -->

| 字段 | 值 |
| --- | --- |
| SQLSTATE | `42P21` |
| 条件名 | `collation_mismatch` |
| 状态 | `有效` |
| 已知存在于 | `9.1.0` |
| 锁定快照 | `9.1.24, 9.2.24, 9.3.25, 9.4.26, 9.5.25, 9.6.24, 10.23, 11.22, 12.22, 13.23, 14.24, 15.19, 16.15, 17.11, 18.6, 19beta3` |
| 宏 | `ERRCODE_COLLATION_MISMATCH` |
| 别名 | `—` |

<!-- source facts: data/errcodes/42P21.json -->
<!-- END SQLSTATE FACTS -->

## 含义 {#meaning}

当固定源码路径需要一个兼容的排序规则，却得到不兼容的选择时，会报 `42P21`。隐式选择会先记录为 `COLLATE_CONFLICT`；调用方允许没有共同排序规则时可以返回 `InvalidOid`，只有确实需要排序规则的调用方才把隐式冲突变成 `ERROR`。显式 `COLLATE` 冲突则立即失败。同一条件还覆盖递归 CTE 输出、继承或子表列定义，以及外键键列兼容性。

## 诊断 {#diagnosis}

遇到隐式排序规则消息时保留两个名称，并检查调用方是否要求共同排序规则；不同的隐式操作数不会全部立即抛出 `42P21`。遇到显式排序规则消息时，找出两个 `COLLATE` 子句并统一预期选择。递归查询要比较非递归项与整体列排序规则。继承或分区子表错误要比较父表与子表列定义。外键要比较引用表和被引用表的键列：固定源码允许两边都是确定性排序规则时使用不同排序规则；只要任一排序规则不确定，两边就必须相同。保留 DETAIL 中的名称，不要把它笼统当成转成 text 就能解决的问题。

## 处理 {#response}

表达式冲突应在表达式边界明确指定一个有意选择的 `COLLATE`，或统一显式子句及递归非递归项的排序规则。重试 DDL 前先对齐继承列或子表列定义。外键应选择兼容的键列排序规则；只要一侧不确定，就满足两边相同的严格要求，然后重新核对相等比较和索引语义。如果该 `ERROR` 发生在显式事务中，修正语句前先 `ROLLBACK`，或回滚到错误前的保存点；自动提交模式下连接回到空闲后再重试。

## 消息 {#messages}

固定源码中的代表性消息包括：

- **ERROR** message: `collation mismatch between implicit collations "%s" and "%s"`; HINT: `You can choose the collation by applying the COLLATE clause to one or both expressions.`
- **ERROR** message: `collation mismatch between explicit collations "%s" and "%s"`
- **ERROR** message: `recursive query "%s" column %d has collation "%s" in non-recursive term but collation "%s" overall`; HINT: `Use the COLLATE clause to set the collation of the non-recursive term.`
- **ERROR** message: `column "%s" has a collation conflict`; DETAIL: `"%s" versus "%s"`
- **ERROR** message: `inherited column "%s" has a collation conflict`; DETAIL: `"%s" versus "%s"`
- **ERROR** message: `child table "%s" has different collation for column "%s"`; DETAIL: `"%s" versus "%s"`
- **ERROR** message: `foreign key constraint "%s" cannot be implemented`; DETAIL: `Key columns "%s" of the referencing table and "%s" of the referenced table have incompatible collations: "%s" and "%s".  If either collation is nondeterministic, then both collations have to be the same.`

占位符由实际对象、列或参数填充。

## 版本 {#versions}

锁定目录显示该条件最早见于 PostgreSQL 9.1.0；行为说明固定在 PostgreSQL 18.6 源码，目录存在范围不等于每条消息或功能都从该版本开始。

## 相关 {#related}

- [`42P22`](../42p22/)
- [`42P18`](../42p18/)

## 来源 {#sources}

源码消息、行号和证据边界见 [作者证据](../../data/evidence/42p21.json)。

- `src/backend/parser/parse_collate.c:208-234` ([fixed source](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/parser/parse_collate.c#L208))
- `src/backend/parser/parse_collate.c:804-835` ([fixed source](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/parser/parse_collate.c#L804))
- `src/backend/parser/parse_cte.c:394-401` ([fixed source](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/parser/parse_cte.c#L394))
- `src/backend/commands/tablecmds.c:3297-3303` ([fixed source](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/commands/tablecmds.c#L3297))
- `src/backend/commands/tablecmds.c:3463-3469` ([fixed source](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/commands/tablecmds.c#L3463))
- `src/backend/commands/tablecmds.c:7292-7298` ([fixed source](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/commands/tablecmds.c#L7292))
- `src/backend/commands/tablecmds.c:10474-10483` ([fixed source](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/commands/tablecmds.c#L10474))
