为何Python从DataFrame生成的列表无法用于Oracle SQL的WHERE IN子句?
问题解决方法
核心原因
从DataFrame的Series直接转tuple时,得到的元组包含的是numpy数值类型(如numpy.int64),而非Python原生的int类型。当用字符串格式化生成SQL语句时,这些numpy类型的字符串表示可能无法被Oracle驱动正确解析,导致SQL执行失败;另外如果Series中存在缺失值(NaN),也会引入无效的NULL值破坏SQL语法。
而手动创建的列表转元组时,元素都是Python原生类型,能被正常解析。
解决方案
方案1:转为原生Python列表后再生成元组
先将Series转为Python原生列表,确保元素类型正确,同时过滤可能存在的空值:
# 从DataFrame提取列并转为原生列表 acc_d1 = data1['ACCOUNT_NUMBER'].tolist() # 过滤空值(如果有需要) acc_d1 = [acc for acc in acc_d1 if pd.notna(acc)] # 转为元组 t1 = tuple(acc_d1) # 生成SQL并执行 sql=""" select id_number from table where account_number IN {}""".format(t1) prog_list_d1 = pd.read_sql(sql, dbc)
方案2:使用参数化查询(更安全,推荐)
避免直接字符串格式化带来的SQL注入风险,同时彻底解决类型匹配问题:
acc_d1 = data1['ACCOUNT_NUMBER'].tolist() acc_d1 = [acc for acc in acc_d1 if pd.notna(acc)] # 生成参数占位符 placeholders = ', '.join([':%d' % idx for idx in range(len(acc_d1))]) sql = f""" select id_number from table where account_number IN ({placeholders}) """ # 传入参数执行查询 prog_list_d1 = pd.read_sql(sql, dbc, params=acc_d1)
内容的提问来源于stack exchange,提问作者halfjain
相关产品推荐
相关产品推荐

