Python MySQL动态插入:列名与值为变量的函数实现求助
解决动态MySQL插入的问题
我看了你的代码,这里有几个关键问题导致它无法正常工作,我来一步步帮你修正:
问题分析
- 错误的列名拼接:
query_columns = ', '.join(stat_name)会把stat_name这个字符串拆成单个字符(比如Enterprise_Value会变成E, n, t, e, r, p, r, i, s, e, _, V, a, l, u, e),这完全不是你想要的列名。 - 混用字符串格式化方式:你同时用了
%和format()两种格式化方法,逻辑混乱,导致SQL语句构造错误。 - 动态列名的处理误区:列名属于SQL标识符,不能用参数化占位符(
%s)来处理,需要直接拼接到SQL语句中(但要注意安全验证);而值才需要用参数化来防止注入。 - 占位符数量计算错误:
query_placeholders = ', '.join(['%s'] * len(stat_value))是用stat_value的字符串长度来生成占位符,这显然不对——你只需要一个占位符对应单个stat_value。
修正后的代码
import pymysql dbname = "mydb" var_table = "exc" symbol = 'ABC' var_date = '20200629' stat_name = 'Enterprise_Value' stat_value = '12345' mypass = "your_password_here" # 记得替换成你的实际密码 def funPopulateTables(symbol, var_date, stat_name, stat_value): # 安全验证:先确认stat_name是表中存在的合法列名,防止SQL注入 allowed_columns = ['Enterprise_Value', 'Profit_Margin', 'EBITDA'] # 换成你实际的列名列表 if stat_name not in allowed_columns: raise ValueError(f"Invalid column name: {stat_name}") conn = pymysql.connect(host="localhost", user="root", passwd=mypass, db=dbname) try: my_cursor = conn.cursor() # 正确构造SQL语句:动态列名直接拼接,值用参数化占位符 add_word = f""" INSERT INTO {var_table} (Symbol, Date, {stat_name}) VALUES (%s, %s, %s) """ data_word = (symbol, var_date, stat_value) my_cursor.execute(add_word, data_word) conn.commit() finally: # 确保连接无论成功失败都会关闭 conn.close() funPopulateTables(symbol, var_date, stat_name, stat_value)
关键改进点
- 安全验证:增加了
allowed_columns白名单,只有在列表中的列名才能被插入,彻底避免SQL注入风险(这一步非常重要,不能省略)。 - 清晰的SQL构造:用f-string直接拼接合法的列名和表名,值部分用参数化占位符
%s,既满足动态需求,又保证安全。 - 可靠的连接管理:用
try...finally确保数据库连接一定会被关闭,避免资源泄漏。
内容的提问来源于stack exchange,提问作者JiggidyJoe
相关产品推荐
相关产品推荐

