L’inserimento di un nome di tabella in una query dà sqlite3.OperationalError: vicino a “?”: Errore di syntax

Voglio scegliere dynamicmente quale tabella utilizzare in una query SQL, ma continuo a ricevere l’errore, tuttavia sto cercando di formattarlo. Anche provato %s invece di ? .

Eventuali suggerimenti?

 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) 

Non è ansible utilizzare i parametri SQL per essere segnaposti in oggetti SQL; uno dei motivi per l’utilizzo di un parametro SQL è di evitare il valore in modo che il database non possa mai scambiare il contenuto per un object di database.

Dovrai interpolare separatamente gli oggetti del database; sfuggi ai tuoi identificatori raddoppiando ogni parametro " doppia quota e usa”

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

e

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

e

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

Le doppie virgolette ".." servono a demarkare correttamente un identificatore, anche se quell’identificatore è anche una parola chiave valida; tutti i " caratteri " esistenti nel nome devono essere raddoppiati, questo aiuta anche a scovare i tentativi di iniezione SQL.

Tuttavia, se i nomi degli oggetti sono di origine utente, dovrai eseguire la tua (rigorosa) validazione sui nomi degli oggetti per evitare attacchi di SQL injection qui. In tal caso, convalidarli sempre con oggetti esistenti.

Dovresti davvero considerare di utilizzare un progetto come SQLAlchemy per generare invece il tuo SQL; può occuparsi della convalida dei nomi degli oggetti e proteggerti rigorosamente dai rischi di iniezione SQL. Può caricare le definizioni della tabella in anticipo in modo da sapere quali nomi sono legali:

 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.