Inserting a table name into a query gives sqlite3.OperationalError: near "?": syntax error Inserting a table name into a query gives sqlite3.OperationalError: near "?": syntax error sqlite sqlite

Inserting a table name into a query gives sqlite3.OperationalError: near "?": syntax error


You cannot use SQL parameters to be placeholders in SQL objects; one of the reasons for using a SQL parameters is to escape the value such that the database can never mistake the contents for a database object.

You'll have to interpolate the database objects separately; escape your identifiers by doubling any " double quote parameters and use

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

and

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

and

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

The ".." double quotes are there to properly demark an identifier, even if that identifier is also a valid keyword; any existing " characters in the name must be doubled; this also helps de-fuse SQL injection attempts.

However, if your object names are user-sourced, you'll have to do your own (stringent) validation on the object names to prevent SQL injection attacks here. Always validate them against existing objects in that case.

You should really consider using a project like SQLAlchemy to generate your SQL instead; it can take care of validating object names and rigorously protect you from SQL injection risks. It can load your table definitions up front so it'll know what names are legal:

from sqlalchemy import create_engine, func, select, MetaDataengine = create_engine('sqlite:////path/to/database')meta = MetaData()meta.reflect(bind=engine)conn = engine.connect()group_table = meta.tables[group]  # can only find existing tablescount_statement = select([func.count(group_table.c.Name)], group_table.c.Name == food)count, = conn.execute(count_statement).fetchone()if count:    # etc.


What are the values of group and food? The guidelines say to make the question as such others can benefit from it, for that to be the case here we need the values of group and food.

It seems you use the Python String formatter instead of SQL parameters for table names even though https://docs.python.org/3/library/sqlite3.html#module-sqlite3 says using the String formatter in unsafe.

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

Using %s as a placeholder then putting % outside the string with the variables in Python2 has been Replaced in Python3 with .format() function with the variables as arguments.


I've found building the SQL query up as a text string and then passing this string into the c.execute() function works.

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

I don't know the security situation around it though (re injection) and I'm sure there are probably better ways of doing this.