Vraag Het invoegen van een tabelnaam in een query geeft sqlite3.OperationalError: near "?": Syntax-fout


Ik wil dynamisch kiezen welke tabel ik wil gebruiken in een SQL-query, maar ik krijg gewoon een foutmelding, maar ik probeer dit te formatteren. Ook geprobeerd %s in plaats van ?.

Suggesties?

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)

19
2017-08-19 15:38


oorsprong


antwoorden:


U kunt SQL-parameters niet gebruiken als tijdelijke aanduiding in SQL-objecten; een van de redenen voor het gebruik van een SQL-parameters is om aan de waarde te ontsnappen, zodat de database de inhoud voor een databaseobject nooit kan verwarren.

U moet de database-objecten afzonderlijk interpoleren; ontsnappen aan je identifiers door ze te verdubbelen " dubbele aanhalingstekens en gebruik

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

en

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

en

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

De ".." dubbele aanhalingstekens zijn er om een ​​identifier correct te demarkeren, zelfs als die identifier ook een geldig sleutelwoord is; een bestaande " tekens in de naam moeten worden verdubbeld; dit helpt ook bij het versmelten van SQL-injectiepogingen.

Als uw objectnamen echter door de gebruiker zijn verkregen, moet u uw eigen (strenge) validatie uitvoeren op de objectnamen om SQL-injectieaanvallen hier te voorkomen. Valideer ze in dat geval altijd tegen bestaande objecten.

Je zou echt moeten overwegen om een ​​project als te gebruiken SQLAlchemy om in plaats daarvan uw SQL te genereren; het kan zorgen voor de validatie van objectnamen en u rigoureus beschermen tegen SQL-injectierisico's. Het kan laad uw tabeldefinities vooraan dus het zal weten welke namen legaal zijn:

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.

36
2017-08-19 15:40