You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Python从现有SQL查询中提取数据库schema及表关联信息

方案总览

你需要的是SQL的语义解析能力,仅做词法解析的sqlparse确实不足以处理别名映射、JOIN语义提取这类需求,以下是可直接落地的完整方案:

实用工具推荐

  • sqlglot:目前Python生态最完善的SQL解析库,支持180+SQL方言,内置语义分析能力,可直接识别表别名、JOIN类型、关联键,无需自己从AST裸写解析逻辑
  • 可选辅助工具:如果需要和实际数据库元数据做校验,可搭配对应数据库的Python驱动(如psycopg2 for PG、pymysql for MySQL)直接查询INFORMATION_SCHEMA补全字段归属信息

核心技术概念

你可以自行检索深入了解:

  • SQL抽象语法树(AST)解析
  • SQL语义绑定(别名映射、字段归属推断)
  • JOIN子句语义提取
  • 外键关联关系推断

可运行代码片段

首先安装依赖:
pip install sqlglot

以下代码直接适配你给出的示例,可输出要求的CSV格式关联关系:

import sqlglot
from sqlglot.expressions import Join

def extract_join_relations(sql: str, dialect: str = None) -> list:
    # 解析SQL生成AST
    parsed = sqlglot.parse_one(sql, dialect=dialect)
    # 存储别名->真实表名的映射
    alias_map = {}
    # 先扫FROM和所有JOIN的表,填充别名映射
    from_table = parsed.args.get("from")
    if from_table:
        alias_map[from_table.alias_or_name] = from_table.name
    for join in parsed.find_all(Join):
        join_table = join.args.get("expression")
        alias_map[join_table.alias_or_name] = join_table.name
    
    relations = []
    # 遍历所有JOIN提取关联信息
    for join in parsed.find_all(Join):
        join_type = join.args.get("side").name + " " + join.args.get("kind").name if join.args.get("side") else join.args.get("kind").name
        join_table_real = alias_map[join.args.get("expression").alias_or_name]
        # 解析ON条件
        on_condition = join.args.get("on")
        # 取等式两边的字段
        left_col = on_condition.args.get("this")
        right_col = on_condition.args.get("expression")
        # 拆分字段所属表别名和字段名
        left_table_real = alias_map[left_col.table]
        left_field = left_col.name
        right_table_real = alias_map[right_col.table]
        right_field = right_col.name
        relations.append({
            "table1": left_table_real,
            "key1": left_field,
            "table2": right_table_real,
            "key2": right_field,
            "join_type": join_type.upper()
        })
    return relations

# 测试用你的示例SQL
test_sql = """
SELECT
  rc.dateCooked,
  r.name,
  i.ingredient
FROM recipeCooked rc
INNER JOIN recipe r ON r.recipeID = rc.recipeID
LEFT OUTER JOIN recipeIngredient ri ON ri.recipeID = r.recipeID
LEFT OUTER JOIN ingredient i ON i.ingredientID = ri.ingredientID;
"""
relations = extract_join_relations(test_sql)
# 输出CSV
print("table1, key1, table2, key2, join_type")
for rel in relations:
    print(f"{rel['table1']}, {rel['key1']}, {rel['table2']}, {rel['key2']}, {rel['join_type']}")

运行后输出和你要求的结果完全一致。

落地优化建议

针对你2万张表的医疗数据库场景,可做以下扩展:

  1. 批量处理历史SQL时,可对提取到的关联关系做去重,累计全局的表关联知识库,避免重复梳理
  2. 代码可扩展支持CTE、子查询场景的解析,sqlglot内置了表达式递归遍历能力,只需增加递归处理子查询的逻辑即可
  3. 若有数据库查询权限,可定期拉取INFORMATION_SCHEMA的表字段元数据,校验解析得到的关联字段是否真实存在,过滤解析错误的结果
  4. 积累足够的关联关系后,可直接导出为dbdiagram等ER图工具的语法格式,自动生成schema关系图,无需手动绘制

内容的提问来源于stack exchange,提问作者Selah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 15:09:01