在查询中插入表名称将得到sqlite3.OperationalError:在“?”附近:语法错误

发布于 2021-01-29 16:14:07

我想动态选择要在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)
关注者
0
被浏览
52
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    您不能将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注入风险。它可以预先加载您的表定义,以便知道哪些名称是合法的:

    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.
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看