修改PostgreSQL生成列逻辑是否会影响已有历史记录?
问题场景
假设我们有一张数据表,表中包含一个生成列,用于拼接两列的字符串值(data_a + data_b),初始表数据如下:
| id | data_a | data_b | generated_data |
|---|---|---|---|
| 1 | abc | 123 | '123abc' |
| 2 | xyz | 890 | 'xyz890' |
现需要修改该生成列的计算逻辑,例如调换字符串拼接顺序为(data_b + data_a),需要确认该修改操作是会回填已有历史记录的生成列值,还是保留旧记录原有值、仅对新插入记录应用新逻辑?
也就是修改后是会出现如下全量回填的效果:
| id | data_a | data_b | generated_data |
|---|---|---|---|
| 1 | abc | 123 | 'abc123' |
| 2 | xyz | 890 | '890xyz' |
| 3 | lmn | 567 | '567lmn' |
还是会出现如下旧值保留的效果?
| id | data_a | data_b | generated_data |
|---|---|---|---|
| 1 | abc | 123 | '123abc' |
| 2 | xyz | 890 | 'xyz890' |
| 3 | lmn | 567 | '567lmn' |
结论
修改生成列计算逻辑后一定会触发全量回填,所有历史数据的生成列值都会按照新逻辑重算,不会保留旧值,不存在仅新数据应用新逻辑的情况。
- 生成列的核心规则就是列值永远和定义的生成表达式、依赖列的值保持一致,不允许同一张表里不同行的生成列套用不同计算逻辑。
- 两类生成列的实际表现一致:
- 虚拟生成列(
VIRTUAL)本身不持久化存储值,查询时才根据表达式实时计算,修改逻辑后所有查询直接走新规则,天然返回新的计算结果。 - 存储型生成列(
STORED)的值是持久化到磁盘的,执行修改生成逻辑的DDL时,数据库会在DDL执行阶段全表扫描,把所有历史行的生成列值按新规则重算并落盘,DDL执行完成后所有行的值都符合新的生成规则。
- 虚拟生成列(
如果DDL执行过程中遇到新表达式计算报错(比如依赖列存在非法值导致计算失败),整个修改操作会直接回滚,不会出现部分行更新、部分行留旧值的中间状态。
内容的提问来源于stack exchange,提问作者Asa LeHolland
相关产品推荐
相关产品推荐

