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

如何用Python精准重命名SQL语句中的表与列(含同名场景)

批量重命名SQL表名:解决表列同名混淆问题

问题背景

需要批量修改多条SQL查询中的指定表名,但遇到以下场景时现有方案失效:

  • 表名与列名同名(如select money from money),正则会误把列名也替换,导致结果不符合预期
  • 同名列存在于不同表中时,批量替换会误改非目标表的列名

之前尝试过的方案均有缺陷:

  • 正则表达式无法覆盖所有边缘场景,无法区分表名和列名的上下文
  • 使用sqlparse、sqlglot库能识别表名,但不知道如何精准修改表名节点,避免影响列名

现有代码问题示例

用正则实现的替换函数会同时修改表名和列名:

import re

def rename_tables(sql, table_names_map):
    for old_table_name, new_table_name in table_names_map.items():
        sql = re.sub(r'\b' + re.escape(old_table_name) + r'\b',
                     new_table_name, sql, flags=re.I)
    return sql

if __name__ == '__main__':
    sql_two = "select money from money"
    rename_dict_two = {'money':'rubber'}
    print(rename_tables(sql_two, rename_dict_two))

执行结果:

select rubber from rubber

期望结果:

select money from rubber

可靠解决方案:基于SQLGlot的AST精准修改

SQLGlot可以将SQL解析为抽象语法树(AST),通过遍历并修改表名节点,实现只替换表名、不影响列名的效果。以下是具体实现:

import sqlglot

def rename_tables_sqlglot(sql, table_names_map):
    # 解析SQL为AST
    parsed = sqlglot.parse_one(sql)
    
    # 遍历所有表引用节点
    for node in parsed.find_all(sqlglot.exp.Table):
        table_name = node.name.lower()
        # 匹配需要替换的表名(不区分大小写)
        for old_name, new_name in table_names_map.items():
            if old_name.lower() == table_name:
                node.set("name", new_name)
                break
    
    # 生成修改后的SQL
    return parsed.sql(dialect=None)

if __name__ == '__main__':
    # 测试场景1:表列同名
    sql_two = "select money from money"
    rename_dict_two = {'money':'rubber'}
    print(rename_tables_sqlglot(sql_two, rename_dict_two))
    
    # 测试场景2:嵌套子查询
    sql_one = "select K.a,K.b from (select H.b from (select G.c from (select F.d from (select E.e from A, B, C, D, E), F), G), H), I, J, K order by 1,2; "
    rename_dict_one = {'A': 'table1', 'B': 'table2', 'C': 'table3', 'D': 'table4', 'E': 'table5', 'F': 'table6', 'G': 'table7', 'H': 'table8', 'I': 'table9', 'J': 'table10', 'K': 'table11'}
    print(rename_tables_sqlglot(sql_one, rename_dict_one))

验证结果

执行上述代码后:

  1. 表列同名场景输出:
SELECT money FROM rubber
  1. 嵌套子查询场景输出:
SELECT K.a, K.b FROM (SELECT H.b FROM (SELECT G.c FROM (SELECT F.d FROM (SELECT E.e FROM table1, table2, table3, table4, table5), table6), table7), table8), table9, table10, table11 ORDER BY 1, 2;

完全符合预期,仅修改表名,列名和嵌套子查询中的表引用均被正确处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 10:25:31