如何在Python中通过for循环批量实现MySQL游标查询并解决语法错误?
如何用Python循环批量实现MySQL多站点数据查询(解决exec语法错误)
问题背景
你原本通过创建多个独立游标来查询不同站点的平均IWV数据,代码可以正常运行,但当需要查询更多站点时,想用循环简化代码,尝试用exec动态创建游标和变量却遇到了语法错误:
exec(cursor{m} = db.cursor()) ^ SyntaxError: invalid syntax
你的原始尝试代码:
for m in range(1,5): exec(f'cursor{m} = db.cursor()') for n in range(1,5): for stat in range(51,55): exec(f'sql_select_AVG{n} = "SELECT AVG(IWV) As AverageIWV FROM GNSS_OUT WHERE StationID={stat} AND Datetime BETWEEN \'2021-05-01\' AND \'2021-05-31\' AND SourceGpsID=23 ;"') exec(f'cursor{n}.executemany(sql_select_AVG{n})') exec(f'yaxis{n}=cursor{n}.fetchall()')
错误原因
虽然你用了f-string,但exec动态创建变量本身就是不推荐的实践——不仅容易出现语法细节错误(比如字符串转义、变量名冲突),还会让代码难以调试和维护。而且你的代码里还有逻辑问题:内层循环多次给同一个sql_select_AVG{n}赋值,最后只会保留最后一个站点的查询语句,完全达不到批量查询的目的。
正确解决方案
我们可以用列表/字典来管理游标和查询结果,既避免动态变量的问题,又让代码更简洁高效。下面提供两种方案:
方案一:循环逐个查询站点(适合需要单独处理每个站点的场景)
# 定义需要查询的站点ID列表 station_ids = list(range(51, 55)) # 对应51、52、53、54四个站点 query_results = [] # 循环处理每个站点 for station_id in station_ids: # 创建游标 cursor = db.cursor() # 使用参数化查询,避免SQL注入,同时简化字符串拼接 sql = """ SELECT AVG(IWV) AS AverageIWV FROM GNSS_OUT WHERE StationID = %s AND Datetime BETWEEN '2021-05-01' AND '2021-05-31' AND SourceGpsID = 23 """ # 执行查询,传入站点ID作为参数 cursor.execute(sql, (station_id,)) # 获取结果:fetchone()返回单个元组,取第一列就是平均IWV avg_iwv = cursor.fetchone()[0] # 将结果存入列表,保留站点ID和对应值 query_results.append({ "station_id": station_id, "average_iwv": avg_iwv }) # 关闭游标,释放资源 cursor.close() # 输出结果 for result in query_results: print(f"站点 {result['station_id']} 的平均IWV: {result['average_iwv']}")
方案二:单SQL批量查询所有站点(更高效,减少数据库交互)
如果不需要单独处理每个站点的查询过程,推荐用IN子句+分组查询,一次获取所有站点的结果,效率更高:
station_ids = list(range(51, 55)) # 构造批量查询的SQL,用IN子句匹配所有站点ID,按StationID分组计算平均值 sql_template = """ SELECT StationID, AVG(IWV) AS AverageIWV FROM GNSS_OUT WHERE StationID IN (%s) AND Datetime BETWEEN '2021-05-01' AND '2021-05-31' AND SourceGpsID = 23 GROUP BY StationID """ # 生成对应数量的占位符(比如4个站点就生成"%s, %s, %s, %s") placeholders = ", ".join(["%s"] * len(station_ids)) # 替换模板中的占位符 final_sql = sql_template % placeholders cursor = db.cursor() # 执行查询,传入站点ID列表作为参数 cursor.execute(final_sql, station_ids) # 获取所有结果 query_results = cursor.fetchall() # 输出结果 for station_id, avg_iwv in query_results: print(f"站点 {station_id} 的平均IWV: {avg_iwv}") cursor.close()
关键注意事项
- 避免使用
exec动态创建变量:用列表、字典等容器来管理数据,代码更易读、易调试。 - 使用参数化查询:不要直接把变量拼接到SQL字符串里,防止SQL注入风险,同时避免字符串转义的麻烦。
- 及时关闭游标:用完游标后记得调用
close(),释放数据库资源。
内容的提问来源于stack exchange,提问作者denbar
相关产品推荐
相关产品推荐

