SQLite参数化查询报错:OperationalError: near "?"语法错误
SQLite参数化查询报错:列名不能用占位符替换
问题场景
使用SQLite合并两个DataFrame时,基础参数化查询可正常执行,但新增列非空筛选逻辑后抛出语法错误。
正常执行的代码
s = path_autre_qdv+'\\' + fichier_in DATA = p.read_csv(s) con = sql.connect('test_db.sqlite') con.create_function('POWER', 2, sqlite_power) c = con.cursor() COM_DETAIL.to_sql('COM_DETAIL_SQL', con, if_exists='replace', index = False) DATA.to_sql('DATA_SQL', con, if_exists='replace', index = False) sq = """ SELECT c.COM_CODE ,c.COM_NAME ,c.COM_LONG ,c.COM_LAT ,d.* FROM COM_DETAIL_SQL c INNER JOIN DATA_SQL d ON POWER((c.COM_LONG - d.longitude)/ ? ,2) + POWER((c.COM_LAT - d.latitude)/ ? ,2) <= 1; """ par = (0.5, 0.5,) RES = read_query(con,sq,par)
报错的代码
s = path_autre_qdv+'\\' + fichier_in DATA = p.read_csv(s) con = sql.connect('test_db.sqlite') con.create_function('POWER', 2, sqlite_power) c = con.cursor() COM_DETAIL.to_sql('COM_DETAIL_SQL', con, if_exists='replace', index = False) DATA.to_sql('DATA_SQL', con, if_exists='replace', index = False) sq = """ SELECT c.COM_CODE ,c.COM_NAME ,c.COM_LONG ,c.COM_LAT ,d.* FROM COM_DETAIL_SQL c INNER JOIN DATA_SQL d ON POWER((c.COM_LONG - d.longitude)/ ? ,2) + POWER((c.COM_LAT - d.latitude)/ ? ,2) <= 1 AND d.? IS NOT NULL AND d.? IS NOT NULL AND d.? IS NOT NULL; """ par = (0.5, 0.5,cinqv,meanv,nonentecinqv,) RES = read_query(con,sq,par)
报错信息
OperationalError: near "?": syntax error
差异说明
报错代码新增了三个参数(cinqv、meanv、nonentecinqv,均为DATA DataFrame的列名),试图用占位符?替换列名来筛选非空值。
原因分析
SQL参数化查询的占位符?仅能用于替换查询中的数值/字符串等值内容,不能用来替换列名、表名这类SQL标识符。当你写d.?时,SQLite无法解析该语法,直接抛出语法错误。
解决方案
由于列名是自身可控的DataFrame列(无外部输入注入风险),可以用字符串格式化提前将列名插入SQL语句,仅对数值部分保留参数化:
修改后的代码示例
s = path_autre_qdv+'\\' + fichier_in DATA = p.read_csv(s) con = sql.connect('test_db.sqlite') con.create_function('POWER', 2, sqlite_power) c = con.cursor() COM_DETAIL.to_sql('COM_DETAIL_SQL', con, if_exists='replace', index = False) DATA.to_sql('DATA_SQL', con, if_exists='replace', index = False) # 提前构造非空筛选条件,用字符串格式化插入列名 cols_to_check = [cinqv, meanv, nonentecinqv] non_null_conditions = " AND ".join([f"d.{col} IS NOT NULL" for col in cols_to_check]) sq = f""" SELECT c.COM_CODE ,c.COM_NAME ,c.COM_LONG ,c.COM_LAT ,d.* FROM COM_DETAIL_SQL c INNER JOIN DATA_SQL d ON POWER((c.COM_LONG - d.longitude)/ ? ,2) + POWER((c.COM_LAT - d.latitude)/ ? ,2) <= 1 AND {non_null_conditions}; """ par = (0.5, 0.5,) RES = read_query(con,sq,par)
特殊情况处理
如果列名包含空格、SQL关键字等特殊字符,需要用双引号包裹列名,修改条件构造逻辑:
non_null_conditions = " AND ".join([f'd."{col}" IS NOT NULL' for col in cols_to_check])
内容的提问来源于stack exchange,提问作者ImFabien75
相关产品推荐
相关产品推荐

