# 428C9 — GENERATED ALWAYS 列赋值

> PostgreSQL SQLSTATE 428C9（generated_always）的来源与诊断参考。
---

# 428C9 — GENERATED ALWAYS 列赋值

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

`428C9`（**generated_always**）是重写阶段的 `ERROR`：INSERT 或 UPDATE 向必须由服务器生成或只接受 `DEFAULT` 的列提供了值。身份列和生成列的赋值规则不同，必须结合操作类型和列元数据判断。

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

| 字段 | 值 |
| --- | --- |
| SQLSTATE | `428C9` |
| 条件名 | `generated_always` |
| 状态 | `有效` |
| 已知存在于 | `10.0` |
| 锁定快照 | `10.23, 11.22, 12.22, 13.23, 14.24, 15.19, 16.15, 17.11, 18.6, 19beta3` |
| 宏 | `ERRCODE_GENERATED_ALWAYS` |
| 别名 | `—` |

<!-- source facts: data/errcodes/428C9.json -->
<!-- END SQLSTATE FACTS -->

## 含义 {#meaning}

重写器会把 INSERT 中省略的目标列或显式 `DEFAULT` 标为 `apply_default`。`GENERATED ALWAYS` 身份列收到非默认值时，除非使用 `OVERRIDING SYSTEM VALUE`，否则报错；`OVERRIDING USER VALUE` 会强制使用默认生成。`BY DEFAULT` 身份列通常允许显式值，但 `OVERRIDING USER VALUE` 仍会强制生成。生成列无论是否有 `OVERRIDING` 都只接受 `DEFAULT`，INSERT 的 DETAIL 会指出列名，身份列分支还带 HINT `Use OVERRIDING SYSTEM VALUE to override.`

UPDATE 的检查覆盖 `GENERATED ALWAYS` 身份列和所有生成列，只要目标项是非默认值就报错；UPDATE 没有 `OVERRIDING` 例外。检查之后，虚拟生成列在重写目标中放入 NULL，存储生成列由执行器填充。这是 18.6 固定源码的存储路径；目录中“10.0 已知存在”只是 SQLSTATE 定义下界，不能据此声称 10.0 已具备所有生成列特性。

## 诊断 {#diagnosis}

检查 `pg_attribute.attidentity`（`a` 表示 `ALWAYS`、`d` 表示 `BY DEFAULT`）和 `attgenerated`（`s` 表示存储、`v` 表示虚拟），确认是 INSERT 还是 UPDATE，以及目标项是省略、`DEFAULT` 还是实际值。`VALUES` 来源还要确认对应行项是否确实为 `DEFAULT`；重写器有单独的全默认判断。身份列与生成列的 INSERT 可能共用主消息，需同时读取 DETAIL/HINT。

## 处理 {#response}

`GENERATED ALWAYS` 身份列省略赋值、使用 `DEFAULT`，或仅在业务明确拥有身份值时使用 `OVERRIDING SYSTEM VALUE`。`BY DEFAULT` 身份列可按业务保留显式值；需要服务器生成时用 `OVERRIDING USER VALUE`。生成列移除赋值，不要用类型转换绕过检查。若 `ERROR` 发生在显式事务中，应回滚到合适保存点或回滚事务后再发修正语句；本页没有运行时恢复观察。

## 消息变体 {#messages}

选定的 18.6 分支均为 `ERROR`：

| 操作 | 主消息 | DETAIL | HINT |
| --- | --- | --- | --- |
| `GENERATED ALWAYS` 身份列 INSERT | `cannot insert a non-DEFAULT value into column "%s"` | `Column "%s" is an identity column defined as GENERATED ALWAYS.` | `Use OVERRIDING SYSTEM VALUE to override.` |
| 生成列 INSERT | `cannot insert a non-DEFAULT value into column "%s"` | `Column "%s" is a generated column.` | 无 |
| `GENERATED ALWAYS` 身份列 UPDATE | `column "%s" can only be updated to DEFAULT` | `Column "%s" is an identity column defined as GENERATED ALWAYS.` | 无 |
| 生成列 UPDATE | `column "%s" can only be updated to DEFAULT` | `Column "%s" is a generated column.` | 无 |

固定源码还区分虚拟生成列的 NULL 目标项与存储生成列的执行器填充。每个 `%s` 都是动态字段，本页不声称具体占位符值或运行时结果。

## 版本 {#versions}

目录记录该条件自 10.0 起存在，并锁定到 18.6、19beta3；这是定义下界，不是身份列、存储生成列和虚拟生成列共同的功能引入版本。本页机制依据 18.6 固定源码，未运行数据库。

## 相关 {#related}

- [`42804`](../42804/)
- [`42601`](../42601/)
- [`23502`](../23502/)

## 来源 {#sources}
- `src.errcodes.428C9.18.6` — `src/backend/utils/errcodes.txt` line 355，固定于 `724edf9bde9d356724ad384a2e196edc3c9f80f7`；SHA-256 `6e8de346643ba84aa3c9c6a73360acfc7b2dfb89162c06c08ce9bf5bcd5bbcba`（[源码](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/errcodes.txt#L355)）。

- `src.call.428C9.353c4cc772b5ae9adad09c67` — `src/backend/rewrite/rewriteHandler.c` lines 942-948，固定于 `724edf9bde9d356724ad384a2e196edc3c9f80f7`；SHA-256 `5a34bf31f424abbf46cd926da1fefcd9360c4d527a87d8a0ac9f653d67c2206a`（[源码](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/rewrite/rewriteHandler.c#L942-L948)）。
- `src.call.428C9.47aaa60ecb1566d462ffaa86` — `src/backend/rewrite/rewriteHandler.c` lines 981-986，固定于 `724edf9bde9d356724ad384a2e196edc3c9f80f7`；SHA-256 `5a34bf31f424abbf46cd926da1fefcd9360c4d527a87d8a0ac9f653d67c2206a`（[源码](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/rewrite/rewriteHandler.c#L981-L986)）。
- `src.call.428C9.8585d423db2446a6222cbf57` — `src/backend/rewrite/rewriteHandler.c` lines 1008-1013，固定于 `724edf9bde9d356724ad384a2e196edc3c9f80f7`；SHA-256 `5a34bf31f424abbf46cd926da1fefcd9360c4d527a87d8a0ac9f653d67c2206a`（[源码](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/rewrite/rewriteHandler.c#L1008-L1013)）。
- `src.call.428C9.generated-update` — `src/backend/rewrite/rewriteHandler.c` lines 1015-1030，固定于 `724edf9bde9d356724ad384a2e196edc3c9f80f7`；SHA-256 `5a34bf31f424abbf46cd926da1fefcd9360c4d527a87d8a0ac9f653d67c2206a`（[源码](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/rewrite/rewriteHandler.c#L1015-L1030)）。
- `src.calls.REL_18_6.428C9` — 固定本地核心调用扫描；SHA-256 `9ee8a0e81d8f0825c5c1ae45583439859a26e602bdd4ce2f2a62aa278867ccbf`。
- [`作者证据`](../../data/evidence/428c9.json) — 记录源码断言、消息角色和运行边界。
