当前位置:首页 > 数据库 > SQlite

python – 在查询中插入表名会产生sqlite3.OperationalError:near“?”:语法错误

我想动态选择在SQL查询中使用哪个表,但我只是不断收到错误,但我正在尝试格式化它.还试过%s而不是?

有什么建议?

group_food = (group, food)
group_food_new = (group, food, 1)

with con:

    cur = con.cursor() 
    tmp = cur.execute("SELECT COUNT(Name) FROM (?) WHERE Name=?", group_food)

    if tmp == 0:
        cur.execute("INSERT INTO ? VALUES(?, ?)", group_food_new)
    else: 
        times_before = cur.execute("SELECT Times FROM ? WHERE Name=?", group_food)
        group_food_update = (group, (times_before +1), food)

        cur.execute("UPDATE ? SET Times=? WHERE Name=?", group_food_update)

解决方法:

您不能将SQL参数用作SQL对象中的占位符;使用SQL参数的原因之一是转义该值,以便数据库永远不会将内容误认为是数据库对象.

您必须单独插入数据库对象;通过加倍任何“双引号参数和使用来逃避您的标识符

cur.execute('SELECT COUNT(Name) FROM "{}" WHERE Name=?'.format(group.replace('"', '""')), (food,))

cur.execute('INSERT INTO "{}" VALUES(?, ?)'.format(group.replace('"', '""')), (food, 1))

cur.execute('UPDATE "{}" SET Times=? WHERE Name=?'.format(group.replace('"', '""')),
            (times_before + 1, food))

“…”双引号用于正确标记标识符,即使该标识符也是有效关键字;名称中任何现有的“字符必须加倍;这也有助于SQL注入尝试的融合.

但是,如果您的对象名称是用户来源的,则必须对对象名称进行自己的(严格的)验证,以防止SQL注入攻击.在这种情况下,始终针对现有对象验证它们.

您应该考虑使用像SQLAlchemy这样的项目来生成SQL;它可以处理验证对象名称并严格保护您免受SQL注入风险.它可以load your table definitions up front所以它会知道什么名称是合法的:

from sqlalchemy import create_engine, func, select, MetaData

engine = create_engine('sqlite:////path/to/database')
meta = MetaData()
meta.reflect(bind=engine)
conn = engine.connect()

group_table = meta.tables[group]  # can only find existing tables
count_statement = select([func.count(group_table.c.Name)], group_table.c.Name == food)
count, = conn.execute(count_statement).fetchone()
if count:
    # etc.

【说明】本文章由站长整理发布,文章内容不代表本站观点,如文中有侵权行为,请与本站客服联系(QQ:254677821)!