爱名网(22科技集团)

动态表单里,字段 key 为什么不能当成字段身份

2026-08-06 11:15老强

动态表单里,字段通常都会有一个 key。刚开始这样用很顺手:保存数据时用 key,查询时用 key,前端提交也是 key。

但项目做久了,会慢慢遇到一些怪问题:字段改名以后,历史数据怎么认;字段删了又新建同名字段,算不算同一个字段;复制表单以后,两个表单里的 mobile 是不是同一个字段。

一、key 更像字段名

key 最大的作用,是让人和程序都知道这个字段叫什么。

record_id   field_key   field_value
---------   ---------   -----------
1           mobile      13800000001
1           status      paid
SELECT field_value
FROM form_record_field
WHERE record_id = 1
  AND field_key = 'mobile';

这个阶段没什么问题。真正的问题是,key 会变。

二、改名以后就乱了

业务人员觉得 mobile 不够准确,想改成 customer_mobile。对页面来说只是改了字段名,但对历史数据来说,这已经是另一个 key。

record_id   field_key          field_value
---------   ----------------   -----------
100         mobile             13800000001
200         customer_mobile    13900000002
SELECT record_id, field_value
FROM form_record_field
WHERE field_key = 'customer_mobile';

如果只查当前 key,老数据就丢了。如果新旧 key 都查,又要先弄清楚它们是不是同一个字段。

三、同名字段也不一定是同一个字段

一个字段被删除后,后来又新建了一个同名字段。名字一样,业务含义不一定一样。

旧字段 status:paid / pending
新字段 status:approved / rejected

如果只用 key 判断,就会把两段数据混在一起。所以 key 适合当字段名,不适合当字段身份。

四、给字段一个稳定身份

更稳的做法,是给每个字段生成一个不会变的身份。

field_uid
字段改名:
field_uid 不变
field_key 可以变

删除字段后再新建同名字段:
field_key 可能一样
field_uid 必须重新生成

五、映射表怎么存

可以单独放一张字段映射表。

CREATE TABLE form_field_identity_map (
    id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
    form_id BIGINT UNSIGNED NOT NULL COMMENT '表单ID',
    field_uid VARCHAR(64) NOT NULL COMMENT '字段稳定身份',
    current_key VARCHAR(100) NOT NULL COMMENT '当前字段key',
    old_keys JSON NULL COMMENT '历史字段key列表',
    field_name VARCHAR(100) NOT NULL DEFAULT '' COMMENT '字段显示名称',
    field_type VARCHAR(50) NOT NULL DEFAULT '' COMMENT '字段类型',
    enabled TINYINT NOT NULL DEFAULT 1 COMMENT '是否启用:1启用,0停用',
    created_at DATETIME NULL COMMENT '创建时间',
    updated_at DATETIME NULL COMMENT '更新时间',
    UNIQUE KEY uk_form_field_uid (form_id, field_uid) COMMENT '同一表单字段身份唯一',
    KEY idx_form_current_key (form_id, current_key) COMMENT '表单当前key索引',
    KEY idx_form_enabled (form_id, enabled) COMMENT '表单启用状态索引'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='表单字段身份映射表';
field_uid 负责识别字段是谁
current_key 负责现在叫什么
old_keys 负责以前叫什么

六、写入时怎么用

写入新数据时,前端通常还是提交 key。

{
  "customer_mobile": "13900000002"
}

后端收到后,先通过当前表单字段配置找到 field_uid。保存 K-V 数据时可以继续保存 field_key,但同步宽表、回填历史数据、做字段映射时,要以 field_uid 为准。

对外用 key
对内认 uid

七、宽表读模型会更需要它

一旦做宽表读模型,field_uid 就很关键。

当前列名:customer_mobile
历史 key:mobile

回填时不能只看当前 key。要先知道 mobile 和 customer_mobile 是不是同一个 field_uid。是同一个,就回填到当前列;不是同一个,就不能混。

八、最后

key 不是不能用。它很适合做字段名、提交名、查询列名。只是不要让它承担“字段身份”这个责任。

key:字段当前名字,给接口、查询和页面用
field_uid:字段稳定身份,给系统内部识别用
old_keys:字段历史名字,给回填和兼容用

把名字和身份分开,后面很多事情都会少绕一点。

曝光874浏览58