为何动态表单中字段 key 不宜用作唯一标识?
本文包含AI辅助创作内容
动态表单里,字段通常都会有一个 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:字段历史名字,给回填和兼容用
把名字和身份分开,后面很多事情都会少绕一点。

请先 登录后发表评论 ~