You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 01:46:32