# DDL Parse API 格式修复说明 ## 问题描述 `/ddl/parse` 接口存在格式不一致的问题: ### 问题1:提示词冲突 在 `DDLParser.parse_ddl()` 方法中存在两个不同的格式要求: - **System Message** 要求单表格式:`table_info + columns` - **User Message** 使用 `_optimize_ddl_prompt()` 要求多表格式:`{table_name: {name_zh, meta: [...]}}` 两个提示词相互冲突,导致LLM返回不确定的格式。 ### 问题2:缺少关键字段 当前格式缺少参考文档中的重要字段: - ❌ `is_primary` - 是否主键 - ❌ `comment` - 注释内容 - ❌ `nullable` - 是否可为空 --- ## 修复方案 ### 1. 统一提示词格式 **修复前**(第86-140行): ```python def parse_ddl(self, sql_content): prompt = self._optimize_ddl_prompt() payload = { "model": self.model_name, "messages": [ { "role": "system", "content": """请从上传的SQL DDL文件中提取数据库表的结构信息... { "table_info": {...}, "columns": [...] } """ }, { "role": "user", "content": f"{prompt}\n\n{sql_content}" } ] } ``` **修复后**: ```python def parse_ddl(self, sql_content): prompt = self._optimize_ddl_prompt() payload = { "model": self.model_name, "messages": [ { "role": "system", "content": "你是一个专业的SQL DDL语句解析专家,擅长从DDL语句中提取表结构信息并转换为结构化的JSON格式。" }, { "role": "user", "content": f"{prompt}\n\n{sql_content}" } ] } ``` ### 2. 更新 `_optimize_ddl_prompt()` 函数 **修复前**(第251-289行): ```python def _optimize_ddl_prompt(self): return """ ... 参考格式如下: { "users_table": { "name_zh": "用户表", "schema": "public", "meta": [{ "name_en": "id", "data_type": "integer", "name_zh": "用户ID" }] } } """ ``` **修复后**: ```python def _optimize_ddl_prompt(self): return """ 请解析以下DDL建表语句,并按照指定的JSON格式返回结果: 规则说明: 1. 从DDL语句中识别所有表,可能会有多个表。每个表作为一个独立条目。 2. 表的英文名称(name_en)使用原始大小写,不要转换为小写。 3. 表的中文名称(name_zh)提取规则: - 优先从COMMENT ON TABLE语句中提取 - 如果没有注释,则name_zh为空字符串 4. 对于每个表,提取所有字段信息到columns数组中,每个字段包含: - name_zh: 字段中文名称 - name_en: 字段英文名称(保持原始大小写) - data_type: 数据类型(包含长度信息,如VARCHAR(22)) - is_primary: 是否主键("是"或"否",从PRIMARY KEY约束判断) - comment: 注释内容(从COMMENT ON COLUMN提取完整注释) - nullable: 是否可为空("是"或"否",从NOT NULL约束判断) 返回格式(支持多表): { "TB_JC_KSDZB": { "table_info": { "name_zh": "科室对照表", "name_en": "TB_JC_KSDZB" }, "columns": [ { "name_zh": "医疗机构代码", "name_en": "YLJGDM", "data_type": "VARCHAR(22)", "is_primary": "是", "comment": "医疗机构代码,复合主键", "nullable": "否" } ] } } """ ``` --- ## 修复后的格式 ### 单表示例(符合参考文档) ```json [ { "table_info": { "name_zh": "科室对照表", "name_en": "TB_JC_KSDZB" }, "columns": [ { "name_zh": "医疗机构代码", "name_en": "YLJGDM", "data_type": "VARCHAR(22)", "is_primary": "是", "comment": "医疗机构代码,复合主键", "nullable": "否" }, { "name_zh": "HIS科室代码", "name_en": "HISKSDM", "data_type": "CHAR(20)", "is_primary": "是", "comment": "HIS科室代码,主键、唯一", "nullable": "否" } ] } ] ``` ### 多表示例 ```json [ { "table_info": { "name_zh": "科室对照表", "name_en": "TB_JC_KSDZB" }, "columns": [...] }, { "table_info": { "name_zh": "用户表", "name_en": "TB_USER" }, "columns": [...] } ] ``` ### API完整响应格式 ```json { "code": 200, "data": [ { "table_info": { "name_zh": "科室对照表", "name_en": "TB_JC_KSDZB" }, "columns": [...] } ], "message": "操作成功" } ``` --- ## 关键改进 ### ✅ 1. 统一提示词 - 删除了冲突的 system message - 只使用 `_optimize_ddl_prompt()` 来定义格式 ### ✅ 2. 添加缺失字段 - `is_primary`: 是否主键("是"/"否") - `comment`: 完整的注释内容 - `nullable`: 是否可为空("是"/"否") ### ✅ 3. 使用标准结构 - `table_info`: 包含表的基本信息 - `columns`: 字段数组,每个字段包含所有必需属性 ### ✅ 4. 保持原始大小写 - 表名和字段名保持原始大小写(如 `TB_JC_KSDZB`, `YLJGDM`) ### ✅ 5. 支持多表 - 使用JSON数组格式返回多个表 - 不使用表名作为key,而是将所有表放在数组中 - 可以一次解析包含多个表的DDL文件 --- ## 测试用例 ### 输入:科室对照表SQL ```sql CREATE TABLE TB_JC_KSDZB ( YLJGDM VARCHAR(22) NOT NULL, HISKSDM CHAR(20) NOT NULL, HISKSMC CHAR(20) NOT NULL, PRIMARY KEY (YLJGDM, HISKSDM) ); COMMENT ON TABLE TB_JC_KSDZB IS '科室对照表'; COMMENT ON COLUMN TB_JC_KSDZB.YLJGDM IS '医疗机构代码,复合主键'; COMMENT ON COLUMN TB_JC_KSDZB.HISKSDM IS 'HIS科室代码,主键、唯一'; COMMENT ON COLUMN TB_JC_KSDZB.HISKSMC IS 'HIS科室名称'; ``` ### 预期输出 ```json [ { "table_info": { "name_zh": "科室对照表", "name_en": "TB_JC_KSDZB" }, "columns": [ { "name_zh": "医疗机构代码", "name_en": "YLJGDM", "data_type": "VARCHAR(22)", "is_primary": "是", "comment": "医疗机构代码,复合主键", "nullable": "否" }, { "name_zh": "HIS科室代码", "name_en": "HISKSDM", "data_type": "CHAR(20)", "is_primary": "是", "comment": "HIS科室代码,主键、唯一", "nullable": "否" }, { "name_zh": "HIS科室名称", "name_en": "HISKSMC", "data_type": "CHAR(20)", "is_primary": "否", "comment": "HIS科室名称", "nullable": "否" } ] } ] ``` --- ## 格式验证清单 - [x] 返回数组格式(支持单表和多表) - [x] 每个表使用 `table_info` + `columns` 结构 - [x] `table_info` 包含 `name_zh` 和 `name_en` - [x] `columns` 是数组,每个元素包含: - [x] `name_zh` - 字段中文名 - [x] `name_en` - 字段英文名 - [x] `data_type` - 数据类型(含长度) - [x] `is_primary` - 是否主键 - [x] `comment` - 注释内容 - [x] `nullable` - 是否可空 - [x] 使用JSON数组格式,不使用表名作为key - [x] 表名和字段名保持原始大小写 --- ## 使用方法 ### 调用接口 ```bash # 方式1:上传SQL文件 curl -X POST http://localhost:5000/api/resource/ddl/parse \ -F "file=@科室对照表_原始.sql" # 方式2:JSON请求 curl -X POST http://localhost:5000/api/resource/ddl/parse \ -H "Content-Type: application/json" \ -d '{"sql": "CREATE TABLE ..."}' ``` ### Python调用 ```python from app.core.llm.ddl_parser import DDLParser # 读取SQL文件 with open('科室对照表_原始.sql', 'r', encoding='utf-8') as f: sql_content = f.read() # 解析DDL parser = DDLParser() result = parser.parse_ddl(sql_content) # 结果格式(数组) # [ # { # "table_info": {...}, # "columns": [...] # } # ] ``` --- ## 文件修改清单 1. **app/core/llm/ddl_parser.py** - 修改 `parse_ddl()` 方法(第86-140行) - 修改 `_optimize_ddl_prompt()` 方法(第251-289行) 2. **接口路由** - `app/api/data_resource/routes.py` - `/ddl/parse` 接口(第602行) --- ## 更新时间 2024-11-27