cursor.fetchone()返回NoneType但有有效值,如何正确收集结果到列表?
问题:查询用户指定列数据时抛出NoneType下标异常
原代码尝试根据用户名查询指定列并收集结果到列表:
def get_user_data(username: str, columns: list): result = [] for column in columns: query = f"SELECT {column} FROM ta_users WHERE username = '{username}'" cursor.execute(query) print('cursor.fetchone() from loop = ', cursor.fetchone(), 'type= ', type(cursor.fetchone())) # debug fetchone = cursor.fetchone() result.append(fetchone[0])
运行时抛出异常:
result.append(fetchone[0])TypeError: 'NoneType' object is not subscriptable
调试打印结果:
cursor.fetchone() from loop = ('6005441021308034',) type= <class 'NoneType'>
问题原因
- 重复调用
fetchone()消耗结果集:调试代码里连续两次调用cursor.fetchone(),第一次调用已经取走了唯一的结果,第二次调用返回None;后续赋值给fetchone的是无效结果,自然无法通过下标访问。 - 未处理空结果场景:当查询不到匹配数据时,
fetchone()会返回None,直接访问下标必然触发异常。 - 存在SQL注入风险:用f-string拼接SQL语句,若用户名包含单引号等特殊字符,会破坏SQL结构,引发注入攻击。
- 查询效率低下:循环查询每一列会产生多次数据库交互,性能损耗大。
修复与优化方案
方案1:修复原逻辑(仅解决异常,仍存注入风险)
保留循环查询逻辑,修正None处理问题:
def get_user_data(username: str, columns: list): result = [] for column in columns: query = f"SELECT {column} FROM ta_users WHERE username = '{username}'" cursor.execute(query) # 仅调用一次fetchone并保存结果 fetchone = cursor.fetchone() print('cursor.fetchone() = ', fetchone, 'type= ', type(fetchone)) # 先判断结果是否为空,再处理 if fetchone is not None: result.append(fetchone[0]) else: # 无数据时添加默认值,可根据需求改为空字符串等 result.append(None) return result
方案2:推荐优化写法(解决注入+提升效率)
一次性查询所有指定列,使用参数化查询避免注入:
def get_user_data(username: str, columns: list): # 将列名拼接为字符串,需确保columns是可信输入(避免非法列名) columns_str = ", ".join(columns) # 用参数化占位符(%s适配MySQL,SQLite用?,需根据数据库类型调整) query = f"SELECT {columns_str} FROM ta_users WHERE username = %s" # 传入参数元组,彻底避免SQL注入 cursor.execute(query, (username,)) # 获取单条结果(假设用户名是唯一标识) row = cursor.fetchone() if row is not None: # 将查询结果行转为列表,顺序与columns参数一致 return list(row) else: # 无匹配用户时,返回对应长度的默认值列表 return [None] * len(columns)
内容的提问来源于stack exchange,提问作者oToMaTiX
相关产品推荐
相关产品推荐

