从注释生成数据字典时,怎么让 AI 写的外键说明跟 DDL 约束对得上

数据库注释和数据字典对不上,90% 的情况不是 AI 生成能力不行,而是你喂给它的上下文里根本没有约束信息。注释里写了一堆业务含义,DDL 里的 FOREIGN KEY ... REFERENCES 却躺在另一个文件里,AI 只能靠猜。要让外键说明和 DDL 对得上,核心是把 DDL 约束和表注释同时喂给模型,再要求它逐条标注约束来源。

先搞清楚为什么会对不上

我最近在一个项目里踩过这个坑。团队用 AI 把 40 多张表的 COMMENT 转成数据字典,外键关系说明写得头头是道,什么「订单表的 user_id 关联用户表主键,表示下单用户」,结果拿到 DBA 那边一审,发现有三处外键在 DDL 里根本不存在——AI 是根据 user_id 这个字段名自己推断出来的。

这不是模型幻觉的问题,是输入信息不足。注释里写「下单用户 ID」,AI 自然会推断它关联用户表。但 DDL 里这个字段可能只是一个普通索引字段,根本没有外键约束,或者约束名是 fk_order_user_ref 而不是 AI 猜的 fk_order_user_id。单看注释,神仙也分不出来。

还有一种情况:DDL 里有外键约束,但注释里压根没提这层关系。比如 order_item 表的 order_id 字段注释是「所属订单」,DDL 里 CONSTRAINT fk_item_order FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE。如果只喂注释,AI 可能写出「关联订单表」,但不会写出 ON DELETE CASCADE 的级联删除行为,更不会写出约束名。

具体做法:把 DDL 和注释拼进同一个上下文

我用过的有效流程是这样的。先把每张表的完整 DDL 和 COMMENT 拼接成一个结构化输入块,格式类似下面这样:

-- 表:order_item
CREATE TABLE order_item (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '明细ID',
  order_id BIGINT UNSIGNED NOT NULL COMMENT '所属订单ID',
  sku_id BIGINT UNSIGNED NOT NULL COMMENT '商品SKU ID',
  quantity INT NOT NULL DEFAULT 1 COMMENT '购买数量',
  PRIMARY KEY (id),
  KEY idx_order (order_id),
  CONSTRAINT fk_item_order FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE,
  CONSTRAINT fk_item_sku FOREIGN KEY (sku_id) REFERENCES sku(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单明细表';

然后给模型的 prompt 要求它做到三点:

  1. 外键说明必须基于 DDL 中实际存在的 FOREIGN KEY 约束来写,不允许根据字段名推断;
  2. 每条外键说明要标注对应的约束名和引用目标;
  3. 如果注释中提到了某字段的关联关系、但 DDL 中没有对应约束,要在输出中单独列出「注释提到但 DDL 未约束」的清单。

这样生成出来的数据字典条目大概长这样:

字段 类型 注释 外键说明
order_id BIGINT UNSIGNED 所属订单ID 外键约束 fk_item_orderorders.id,级联删除(ON DELETE CASCADE)
sku_id BIGINT UNSIGNED 商品SKU ID 外键约束 fk_item_skusku.id

关键点在于:约束名是从 DDL 里抄的,不是 AI 编的。后续 DBA 核对时,拿约束名去 information_schema.TABLE_CONSTRAINTS 里一查就能验证。

交叉验证环节:让 AI 自己写校验 SQL

生成完数据字典还不够,我还会让 AI 顺手生成一段校验 SQL,用来在数据库里验证它写的外键说明是否和实际约束一致。Prompt 大概是这样:

根据上面生成的数据字典,写一段 SQL 查询 information_schema,列出所有外键约束的名称、来源表、来源字段、引用表、引用字段、删除规则和更新规则,用来和文档中的外键说明逐条比对。

AI 会输出类似下面的 SQL:

SELECT
  tc.CONSTRAINT_NAME AS constraint_name,
  kcu.TABLE_NAME AS source_table,
  kcu.COLUMN_NAME AS source_column,
  kcu.REFERENCED_TABLE_NAME AS referenced_table,
  kcu.REFERENCED_COLUMN_NAME AS referenced_column,
  rc.DELETE_RULE AS delete_rule,
  rc.UPDATE_RULE AS update_rule
FROM information_schema.TABLE_CONSTRAINTS tc
JOIN information_schema.KEY_COLUMN_USAGE kcu
  ON tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME
 AND tc.TABLE_SCHEMA = kcu.TABLE_SCHEMA
JOIN information_schema.REFERENTIAL_CONSTRAINTS rc
  ON tc.CONSTRAINT_NAME = rc.CONSTRAINT_NAME
 AND tc.TABLE_SCHEMA = rc.CONSTRAINT_SCHEMA
WHERE tc.CONSTRAINT_TYPE = 'FOREIGN KEY'
  AND tc.TABLE_SCHEMA = 'your_database_name'
ORDER BY tc.TABLE_NAME, tc.CONSTRAINT_NAME;

跑一遍这个 SQL,导出一份实际约束清单,跟 AI 生成的数据字典逐条 diff。对不上的地方分两类处理:

  • 文档有、数据库没有:AI 根据注释推断出来的「伪外键」,要么删掉说明,要么改成「逻辑关联,无数据库级外键约束」;
  • 数据库有、文档漏了:把约束信息补进数据字典,同时回头检查是不是注释里缺少了这层业务说明。

这个 diff 过程也可以让 AI 来做——把 SQL 查询结果和生成的数据字典都丢给它,让它找出不一致项。但最终裁决必须人工过一遍,特别是涉及级联删除规则的描述,写错了会误导后续做数据迁移的人。

批量处理时的一个坑

表多了以后,上下文长度是个实际问题。50 张表的 DDL 加注释,轻轻松松超过 3 万 token。分块处理时要注意:不要把一张表的 DDL 和它的注释拆到两个块里。我见过有人把全部注释放一个文件、全部 DDL 放另一个文件,分别喂给 AI 再合并结果,这样外键说明还是靠猜。

正确的分块方式是按表或按模块分,每个块内同时包含该表的 DDL 和注释。如果表之间有外键引用关系,尽量把引用方和被引用方放在同一个块里。比如 ordersorder_item 必须一起处理,否则 AI 写 order_item 的外键说明时看不到 orders 表的 DDL,只能靠表名猜主键字段是 id 还是 order_id 还是别的什么。

我实际用过的分块策略是:先按外键依赖关系做拓扑排序,把强关联的表聚成一组,每组控制在 15-20 张表以内。这样每组大约 8000-12000 token,AI 处理起来不吃力,外键关系也不会被截断。

如果 DDL 里根本没有外键约束

还有一种更常见的情况:生产库为了性能压根不建外键,约束全靠应用层维护。这时候注释里写的「关联用户表」就是纯逻辑关系,没有 DDL 约束可对。

这种场景下,要让 AI 把「逻辑外键」和「物理外键」分开标注。Prompt 里要明确加一条:

DDL 中没有 FOREIGN KEY 约束的字段,即使注释中提到了关联关系,也必须标注为「逻辑关联(无物理外键约束)」,不得使用「外键约束」字样。

数据字典里多出一列「约束类型」,写清楚是 PHYSICAL 还是 LOGICAL。这样 DBA 看到文档时不会误以为数据库里有级联删除保护,开发看到时也知道删数据前得自己在代码里检查引用。


常见问题

AI 生成的外键说明和 DDL 对不上,但注释里明明写清楚了关联关系,为什么会这样?

因为 AI 没有看到 DDL 文件。注释里的「关联」「所属」等字眼只能说明存在逻辑关系,无法说明数据库层面是否真的建了 FOREIGN KEY 约束。把完整 DDL 和注释放在同一个输入块里,并在 prompt 中明确要求「外键说明必须引用 DDL 中实际存在的约束名」,这个问题基本就能解决。

怎么验证数据字典里的外键说明是不是真的和数据库一致?

information_schema.REFERENTIAL_CONSTRAINTSKEY_COLUMN_USAGE 的查询,导出实际约束清单,和文档逐条比对。约束名、引用表、引用字段、删除规则、更新规则这五要素都对齐才算一致。如果文档里写了约束名但数据库里查不到,大概率是 AI 编的。

DDL 里没有外键约束,但注释里提到了关联关系,数据字典里应该怎么写?

写「逻辑关联(无物理外键约束)」,不要写「外键约束」。同时在数据字典中增加「约束类型」列,区分 PHYSICALLOGICAL。这样文档读者能明确知道:删这条数据时数据库不会拦截,需要在应用层自行处理引用完整性。

批量处理几十张表时,怎么防止 AI 漏掉跨表外键?

按外键依赖关系分块,保证引用方和被引用方在同一个输入块内。不要按字母顺序或文件顺序随意切分,否则 order_item 的外键说明可能因为看不到 orders 表的 DDL 而写错主键字段。每组控制在 15-20 张表以内,既保证上下文长度可控,又保证关联关系完整。