Python 在查询中插入表名会产生sqlite3.ERROR:near“QUOTE;”&引用;:语法错误

Python 在查询中插入表名会产生sqlite3.ERROR:near“QUOTE;”&引用;:语法错误,python,python-2.7,sqlite,Python,Python 2.7,Sqlite,我想动态地选择在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 ==

我想动态地选择在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,))

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

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

<>你应该考虑使用一个类似于生成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.

团体和食物的价值是什么?指导方针说,要使这个问题成为其他人可以从中受益的问题,要做到这一点,我们需要群体和食物的价值观

似乎您对表名使用Python字符串格式化程序而不是SQL参数,尽管在“不安全”中说使用字符串格式化程序

# Never do this -- insecure!
symbol = 'RHAT'
c.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol)

# Do this instead
t = ('RHAT',)
c.execute('SELECT * FROM stocks WHERE symbol=?', t)

使用
%s
作为占位符,然后将
%
放在Python2中带有变量的字符串外部,这在Python3中已被替换为带有变量的
.format()
函数。

我发现将SQL查询构建为文本字符串,然后将该字符串传递到c.execute()函数中是可行的

querySelect = "SELECT * FROM " + str(your_table_variable)
queryWhere = " WHERE " + str(variableName) + " = " str(variableValue)
query = querySelect + queryWhere
c.execute(query)

我不知道它周围的安全情况(重新注入),我相信可能有更好的方法来做到这一点。

啊!所以“?”占位符只用于SQL值,不能用于SQL表名等?@colminator:没错。否则会有一个巨大的安全漏洞,有人会在其中添加
;删除表值--
,或其他类似的恶作剧。这是使用SQL参数的主要原因之一(始终使用SQL参数,这是安全的!)。从值的角度理解,但我指的是表和列名。我一直希望以一种通用的方式将SQL参数化的便利性扩展到表名和列。例如,在比较两个具有不同模式(即列不匹配)的数据库时,我希望以编程方式确定导入和导出列。虽然列名中不应该有任何特殊字符,但最好安全地对它们进行转义,以消除任何可能的SQL错误。@colminator:不,对象名确实不能与参数一起使用。对于类似这样的任务,请使用SQL生成器(如SQLAlchemy)或。@hellogoodbay:因为参数的用例是转义数据,而检测某个对象是否是对象名并不容易。例如,您无法从上下文中确定某个内容是否用作数据或对象名<代码>其中colname=?可以同时使用对象名和数据。不要这样做。这是注射的定义。
# Never do this -- insecure!
symbol = 'RHAT'
c.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol)

# Do this instead
t = ('RHAT',)
c.execute('SELECT * FROM stocks WHERE symbol=?', t)
querySelect = "SELECT * FROM " + str(your_table_variable)
queryWhere = " WHERE " + str(variableName) + " = " str(variableValue)
query = querySelect + queryWhere
c.execute(query)