Discord机器人!set-stats命令SQLite列名匹配错误求助
问题根源与解决方案
你遇到的sqlite3.OperationalError: no such column: Ninjutsu Mastery,本质是代码中使用的用户友好型属性名(带空格、首字母大写)和数据库列名(下划线分隔、全小写)格式不匹配——SQL解析时会把带空格的字符串当成列名,自然找不到对应字段。
修复方案
方案1:手动维护属性名-列名映射表
适合属性数量不多、命名规则不统一的场景,直接建立友好名称到数据库列名的对应关系:
# 定义映射字典:用户输入的属性名 -> 数据库列名 STAT_MAPPING = { "Ninjutsu Mastery": "ninjutsu_mastery", "Taijutsu Proficiency": "taijutsu_proficiency", "Genjutsu Skill": "genjutsu_skill", # 补充其他属性的对应关系 } # 在!set-stats命令逻辑中使用映射 @bot.command(name="set-stats") async def set_stats(ctx, stat_name: str, value: int): # 转换属性名为数据库列名 column_name = STAT_MAPPING.get(stat_name) if not column_name: await ctx.send(f"不存在的属性:{stat_name}") return # 假设已经获取到目标用户ID user_id = ctx.author.id try: # 执行参数化SQL更新(避免注入风险) cursor.execute(f"UPDATE characters SET {column_name} = ? WHERE user_id = ?", (value, user_id)) conn.commit() await ctx.send(f"已成功更新{stat_name}为{value}") except sqlite3.Error as e: await ctx.send(f"更新失败:{str(e)}")
方案2:自动格式转换
如果所有属性名都是「空格分隔的首字母大写」对应「下划线分隔的全小写」,可以写一个转换函数自动处理,无需手动维护映射表:
def convert_to_column_name(stat_name): # 转换规则:大写转小写,空格替换为下划线 return stat_name.lower().replace(" ", "_") # 在命令中使用 @bot.command(name="set-stats") async def set_stats(ctx, stat_name: str, value: int): column_name = convert_to_column_name(stat_name) # 可选:验证列名是否真实存在于数据库表中(防止恶意输入) cursor.execute("PRAGMA table_info(characters)") valid_columns = [row[1] for row in cursor.fetchall()] if column_name not in valid_columns: await ctx.send(f"不存在的属性:{stat_name}") return user_id = ctx.author.id try: cursor.execute(f"UPDATE characters SET {column_name} = ? WHERE user_id = ?", (value, user_id)) conn.commit() await ctx.send(f"已成功更新{stat_name}为{value}") except sqlite3.Error as e: await ctx.send(f"更新失败:{str(e)}")
验证步骤
- 修改代码后重启Discord机器人
- 执行命令
!set-stats "Ninjutsu Mastery" 90 - 检查
characters表中对应用户的ninjutsu_mastery列值是否更新为90 - 确认不再抛出
no such column错误
内容的提问来源于stack exchange,提问作者Дарина Георгиева
相关产品推荐
相关产品推荐

